1*3d5d9f5aSJerome Forissier /* 2*3d5d9f5aSJerome Forissier * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. 3*3d5d9f5aSJerome Forissier * 4*3d5d9f5aSJerome Forissier * SPDX-License-Identifier: BSD-3-Clause 5*3d5d9f5aSJerome Forissier */ 6*3d5d9f5aSJerome Forissier 7*3d5d9f5aSJerome Forissier #include <assert.h> 8*3d5d9f5aSJerome Forissier #include <debug.h> 9*3d5d9f5aSJerome Forissier #include <platform_def.h> 10*3d5d9f5aSJerome Forissier #include <stdint.h> 11*3d5d9f5aSJerome Forissier #include <strings.h> 12*3d5d9f5aSJerome Forissier #include <utils_def.h> 13*3d5d9f5aSJerome Forissier #include "hikey_private.h" 14*3d5d9f5aSJerome Forissier 15*3d5d9f5aSJerome Forissier #define PORTNUM_MAX 5 16*3d5d9f5aSJerome Forissier 17*3d5d9f5aSJerome Forissier #define MDDRC_SECURITY_BASE 0xF7121000 18*3d5d9f5aSJerome Forissier 19*3d5d9f5aSJerome Forissier struct int_en_reg { 20*3d5d9f5aSJerome Forissier unsigned in_en:1; 21*3d5d9f5aSJerome Forissier unsigned reserved:31; 22*3d5d9f5aSJerome Forissier }; 23*3d5d9f5aSJerome Forissier 24*3d5d9f5aSJerome Forissier struct rgn_map_reg { 25*3d5d9f5aSJerome Forissier unsigned rgn_base_addr:24; 26*3d5d9f5aSJerome Forissier unsigned rgn_size:6; 27*3d5d9f5aSJerome Forissier unsigned reserved:1; 28*3d5d9f5aSJerome Forissier unsigned rgn_en:1; 29*3d5d9f5aSJerome Forissier }; 30*3d5d9f5aSJerome Forissier 31*3d5d9f5aSJerome Forissier struct rgn_attr_reg { 32*3d5d9f5aSJerome Forissier unsigned sp:4; 33*3d5d9f5aSJerome Forissier unsigned security_inv:1; 34*3d5d9f5aSJerome Forissier unsigned reserved_0:3; 35*3d5d9f5aSJerome Forissier unsigned mid_en:1; 36*3d5d9f5aSJerome Forissier unsigned mid_inv:1; 37*3d5d9f5aSJerome Forissier unsigned reserved_1:6; 38*3d5d9f5aSJerome Forissier unsigned rgn_en:1; 39*3d5d9f5aSJerome Forissier unsigned subrgn_disable:16; 40*3d5d9f5aSJerome Forissier }; 41*3d5d9f5aSJerome Forissier 42*3d5d9f5aSJerome Forissier static volatile struct int_en_reg *get_int_en_reg(uint32_t base) 43*3d5d9f5aSJerome Forissier { 44*3d5d9f5aSJerome Forissier uint64_t addr = base + 0x20; 45*3d5d9f5aSJerome Forissier return (struct int_en_reg *)addr; 46*3d5d9f5aSJerome Forissier } 47*3d5d9f5aSJerome Forissier 48*3d5d9f5aSJerome Forissier static volatile struct rgn_map_reg *get_rgn_map_reg(uint32_t base, int region, int port) 49*3d5d9f5aSJerome Forissier { 50*3d5d9f5aSJerome Forissier uint64_t addr = base + 0x100 + 0x10 * region + 0x400 * (uint64_t)port; 51*3d5d9f5aSJerome Forissier return (struct rgn_map_reg *)addr; 52*3d5d9f5aSJerome Forissier } 53*3d5d9f5aSJerome Forissier 54*3d5d9f5aSJerome Forissier static volatile struct rgn_attr_reg *get_rgn_attr_reg(uint32_t base, int region, 55*3d5d9f5aSJerome Forissier int port) 56*3d5d9f5aSJerome Forissier { 57*3d5d9f5aSJerome Forissier uint64_t addr = base + 0x104 + 0x10 * region + 0x400 * (uint64_t)port; 58*3d5d9f5aSJerome Forissier return (struct rgn_attr_reg *)addr; 59*3d5d9f5aSJerome Forissier } 60*3d5d9f5aSJerome Forissier 61*3d5d9f5aSJerome Forissier /* 62*3d5d9f5aSJerome Forissier * Configure secure memory region 63*3d5d9f5aSJerome Forissier * region_size must be a power of 2 and at least 64KB 64*3d5d9f5aSJerome Forissier * region_base must be region_size aligned 65*3d5d9f5aSJerome Forissier */ 66*3d5d9f5aSJerome Forissier static void sec_protect(uint32_t region_base, uint32_t region_size) 67*3d5d9f5aSJerome Forissier { 68*3d5d9f5aSJerome Forissier volatile struct int_en_reg *int_en; 69*3d5d9f5aSJerome Forissier volatile struct rgn_map_reg *rgn_map; 70*3d5d9f5aSJerome Forissier volatile struct rgn_attr_reg *rgn_attr; 71*3d5d9f5aSJerome Forissier uint32_t i = 0; 72*3d5d9f5aSJerome Forissier 73*3d5d9f5aSJerome Forissier assert(!IS_POWER_OF_TWO(region_size) || region_size < 0x10000); 74*3d5d9f5aSJerome Forissier /* ensure secure region_base is aligned to region_size */ 75*3d5d9f5aSJerome Forissier assert((region_base & (region_size - 1))); 76*3d5d9f5aSJerome Forissier 77*3d5d9f5aSJerome Forissier INFO("BL2: TrustZone: protecting %u bytes of memory at 0x%x\n", region_size, 78*3d5d9f5aSJerome Forissier region_base); 79*3d5d9f5aSJerome Forissier 80*3d5d9f5aSJerome Forissier int_en = get_int_en_reg(MDDRC_SECURITY_BASE); 81*3d5d9f5aSJerome Forissier int_en->in_en = 0x1; 82*3d5d9f5aSJerome Forissier 83*3d5d9f5aSJerome Forissier for (i = 0; i < PORTNUM_MAX; i++) { 84*3d5d9f5aSJerome Forissier rgn_map = get_rgn_map_reg(MDDRC_SECURITY_BASE, 1, i); 85*3d5d9f5aSJerome Forissier rgn_attr = get_rgn_attr_reg(MDDRC_SECURITY_BASE, 1, i); 86*3d5d9f5aSJerome Forissier rgn_map->rgn_base_addr = region_base >> 16; 87*3d5d9f5aSJerome Forissier rgn_attr->subrgn_disable = 0x0; 88*3d5d9f5aSJerome Forissier rgn_attr->sp = (i == 3) ? 0xC : 0x0; 89*3d5d9f5aSJerome Forissier rgn_map->rgn_size = __builtin_ffs(region_size) - 2; 90*3d5d9f5aSJerome Forissier rgn_map->rgn_en = 0x1; 91*3d5d9f5aSJerome Forissier } 92*3d5d9f5aSJerome Forissier } 93*3d5d9f5aSJerome Forissier 94*3d5d9f5aSJerome Forissier /******************************************************************************* 95*3d5d9f5aSJerome Forissier * Initialize the secure environment. 96*3d5d9f5aSJerome Forissier ******************************************************************************/ 97*3d5d9f5aSJerome Forissier void hikey_security_setup(void) 98*3d5d9f5aSJerome Forissier { 99*3d5d9f5aSJerome Forissier sec_protect(DDR_SEC_BASE, DDR_SEC_SIZE); 100*3d5d9f5aSJerome Forissier } 101