123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- /*
- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <assert.h>
- #include <common/debug.h>
- #include <drivers/arm/tzc_dmc620.h>
- #include <lib/mmio.h>
- /* 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");
- }
|