146f9b2c3SPeng Fan /*
246f9b2c3SPeng Fan * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
346f9b2c3SPeng Fan *
446f9b2c3SPeng Fan * SPDX-License-Identifier: BSD-3-Clause
546f9b2c3SPeng Fan */
646f9b2c3SPeng Fan
746f9b2c3SPeng Fan #include <assert.h>
846f9b2c3SPeng Fan #include <stddef.h>
909d40e0eSAntonio Nino Diaz
1009d40e0eSAntonio Nino Diaz #include <common/debug.h>
1109d40e0eSAntonio Nino Diaz #include <drivers/arm/tzc380.h>
1209d40e0eSAntonio Nino Diaz #include <lib/mmio.h>
1346f9b2c3SPeng Fan
1446f9b2c3SPeng Fan struct tzc380_instance {
1546f9b2c3SPeng Fan uintptr_t base;
1646f9b2c3SPeng Fan uint8_t addr_width;
1746f9b2c3SPeng Fan uint8_t num_regions;
1846f9b2c3SPeng Fan };
1946f9b2c3SPeng Fan
2046f9b2c3SPeng Fan struct tzc380_instance tzc380;
2146f9b2c3SPeng Fan
tzc380_read_build_config(uintptr_t base)2246f9b2c3SPeng Fan static unsigned int tzc380_read_build_config(uintptr_t base)
2346f9b2c3SPeng Fan {
2446f9b2c3SPeng Fan return mmio_read_32(base + TZC380_CONFIGURATION_OFF);
2546f9b2c3SPeng Fan }
2646f9b2c3SPeng Fan
tzc380_write_action(uintptr_t base,unsigned int action)27*cc69cfd2SAmbroise Vincent static void tzc380_write_action(uintptr_t base, unsigned int action)
2846f9b2c3SPeng Fan {
2946f9b2c3SPeng Fan mmio_write_32(base + ACTION_OFF, action);
3046f9b2c3SPeng Fan }
3146f9b2c3SPeng Fan
tzc380_write_region_base_low(uintptr_t base,unsigned int region,unsigned int val)3246f9b2c3SPeng Fan static void tzc380_write_region_base_low(uintptr_t base, unsigned int region,
3346f9b2c3SPeng Fan unsigned int val)
3446f9b2c3SPeng Fan {
3546f9b2c3SPeng Fan mmio_write_32(base + REGION_SETUP_LOW_OFF(region), val);
3646f9b2c3SPeng Fan }
3746f9b2c3SPeng Fan
tzc380_write_region_base_high(uintptr_t base,unsigned int region,unsigned int val)3846f9b2c3SPeng Fan static void tzc380_write_region_base_high(uintptr_t base, unsigned int region,
3946f9b2c3SPeng Fan unsigned int val)
4046f9b2c3SPeng Fan {
4146f9b2c3SPeng Fan mmio_write_32(base + REGION_SETUP_HIGH_OFF(region), val);
4246f9b2c3SPeng Fan }
4346f9b2c3SPeng Fan
tzc380_write_region_attributes(uintptr_t base,unsigned int region,unsigned int val)4446f9b2c3SPeng Fan static void tzc380_write_region_attributes(uintptr_t base, unsigned int region,
4546f9b2c3SPeng Fan unsigned int val)
4646f9b2c3SPeng Fan {
4746f9b2c3SPeng Fan mmio_write_32(base + REGION_ATTRIBUTES_OFF(region), val);
4846f9b2c3SPeng Fan }
4946f9b2c3SPeng Fan
tzc380_init(uintptr_t base)5046f9b2c3SPeng Fan void tzc380_init(uintptr_t base)
5146f9b2c3SPeng Fan {
5246f9b2c3SPeng Fan unsigned int tzc_build;
5346f9b2c3SPeng Fan
54df54406dSAntonio Nino Diaz assert(base != 0U);
5546f9b2c3SPeng Fan tzc380.base = base;
5646f9b2c3SPeng Fan
5746f9b2c3SPeng Fan /* Save values we will use later. */
5846f9b2c3SPeng Fan tzc_build = tzc380_read_build_config(tzc380.base);
5946f9b2c3SPeng Fan tzc380.addr_width = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) &
6046f9b2c3SPeng Fan BUILD_CONFIG_AW_MASK) + 1;
6146f9b2c3SPeng Fan tzc380.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) &
6246f9b2c3SPeng Fan BUILD_CONFIG_NR_MASK) + 1;
6346f9b2c3SPeng Fan }
6446f9b2c3SPeng Fan
addr_low(uintptr_t addr)6546f9b2c3SPeng Fan static uint32_t addr_low(uintptr_t addr)
6646f9b2c3SPeng Fan {
6746f9b2c3SPeng Fan return (uint32_t)addr;
6846f9b2c3SPeng Fan }
6946f9b2c3SPeng Fan
addr_high(uintptr_t addr __unused)7046f9b2c3SPeng Fan static uint32_t addr_high(uintptr_t addr __unused)
7146f9b2c3SPeng Fan {
7246f9b2c3SPeng Fan #if (UINTPTR_MAX == UINT64_MAX)
7346f9b2c3SPeng Fan return addr >> 32;
7446f9b2c3SPeng Fan #else
7546f9b2c3SPeng Fan return 0;
7646f9b2c3SPeng Fan #endif
7746f9b2c3SPeng Fan }
7846f9b2c3SPeng Fan
7946f9b2c3SPeng Fan /*
8046f9b2c3SPeng Fan * `tzc380_configure_region` is used to program regions into the TrustZone
8146f9b2c3SPeng Fan * controller.
8246f9b2c3SPeng Fan */
tzc380_configure_region(uint8_t region,uintptr_t region_base,unsigned int attr)8346f9b2c3SPeng Fan void tzc380_configure_region(uint8_t region, uintptr_t region_base, unsigned int attr)
8446f9b2c3SPeng Fan {
85df54406dSAntonio Nino Diaz assert(tzc380.base != 0U);
8646f9b2c3SPeng Fan
8746f9b2c3SPeng Fan assert(region < tzc380.num_regions);
8846f9b2c3SPeng Fan
8946f9b2c3SPeng Fan tzc380_write_region_base_low(tzc380.base, region, addr_low(region_base));
9046f9b2c3SPeng Fan tzc380_write_region_base_high(tzc380.base, region, addr_high(region_base));
9146f9b2c3SPeng Fan tzc380_write_region_attributes(tzc380.base, region, attr);
9246f9b2c3SPeng Fan }
9346f9b2c3SPeng Fan
tzc380_set_action(unsigned int action)94*cc69cfd2SAmbroise Vincent void tzc380_set_action(unsigned int action)
9546f9b2c3SPeng Fan {
96df54406dSAntonio Nino Diaz assert(tzc380.base != 0U);
9746f9b2c3SPeng Fan
9846f9b2c3SPeng Fan /*
9946f9b2c3SPeng Fan * - Currently no handler is provided to trap an error via interrupt
10046f9b2c3SPeng Fan * or exception.
10146f9b2c3SPeng Fan * - The interrupt action has not been tested.
10246f9b2c3SPeng Fan */
10346f9b2c3SPeng Fan tzc380_write_action(tzc380.base, action);
10446f9b2c3SPeng Fan }
105