1 /* 2 * Copyright (c) 2019-2022, Arm Limited. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 9 #include <arch_helpers.h> 10 #include <common/debug.h> 11 #include <drivers/delay_timer.h> 12 #include <lib/bakery_lock.h> 13 #include <lib/mmio.h> 14 15 #include "corstone700_mhu.h" 16 #include <plat_arm.h> 17 #include <platform_def.h> 18 19 ARM_INSTANTIATE_LOCK; 20 21 #pragma weak plat_arm_pwrc_setup 22 23 /* 24 * Slot 31 is reserved because the MHU hardware uses this register bit to 25 * indicate a non-secure access attempt. The total number of available slots is 26 * therefore 31 [30:0]. 27 */ 28 #define MHU_MAX_SLOT_ID 30 29 30 void mhu_secure_message_start(uintptr_t address, unsigned int slot_id) 31 { 32 unsigned int intr_stat_check; 33 uint64_t timeout_cnt; 34 volatile uint8_t expiration; 35 36 assert(slot_id <= MHU_MAX_SLOT_ID); 37 arm_lock_get(); 38 39 /* 40 * Make sure any previous command has finished 41 * and polling timeout not expired 42 */ 43 44 timeout_cnt = timeout_init_us(MHU_POLL_INTR_STAT_TIMEOUT); 45 46 do { 47 intr_stat_check = (mmio_read_32(address + CPU_INTR_S_STAT) & 48 (1 << slot_id)); 49 50 expiration = timeout_elapsed(timeout_cnt); 51 52 } while ((intr_stat_check != 0U) && (expiration == 0U)); 53 54 /* 55 * Note: No risk of timer overflows while waiting 56 * for the timeout expiration. 57 * According to Armv8 TRM: System counter roll-over 58 * time of not less than 40 years 59 */ 60 } 61 62 void mhu_secure_message_send(uintptr_t address, 63 unsigned int slot_id, 64 unsigned int message) 65 { 66 unsigned char access_ready; 67 uint64_t timeout_cnt; 68 volatile uint8_t expiration; 69 70 assert(slot_id <= MHU_MAX_SLOT_ID); 71 assert((mmio_read_32(address + CPU_INTR_S_STAT) & 72 (1 << slot_id)) == 0U); 73 74 MHU_V2_ACCESS_REQUEST(address); 75 76 timeout_cnt = timeout_init_us(MHU_POLL_INTR_STAT_TIMEOUT); 77 78 do { 79 access_ready = MHU_V2_IS_ACCESS_READY(address); 80 expiration = timeout_elapsed(timeout_cnt); 81 82 } while ((access_ready == 0U) && (expiration == 0U)); 83 84 /* 85 * Note: No risk of timer overflows while waiting 86 * for the timeout expiration. 87 * According to Armv8 TRM: System counter roll-over 88 * time of not less than 40 years 89 */ 90 91 mmio_write_32(address + CPU_INTR_S_SET, message); 92 } 93 94 void mhu_secure_message_end(uintptr_t address, unsigned int slot_id) 95 { 96 assert(slot_id <= MHU_MAX_SLOT_ID); 97 /* 98 * Clear any response we got by writing one in the relevant slot bit to 99 * the CLEAR register 100 */ 101 MHU_V2_CLEAR_REQUEST(address); 102 103 arm_lock_release(); 104 } 105 106 void __init mhu_secure_init(void) 107 { 108 arm_lock_init(); 109 110 /* 111 * The STAT register resets to zero. Ensure it is in the expected state, 112 * as a stale or garbage value would make us think it's a message we've 113 * already sent. 114 */ 115 116 assert(mmio_read_32(PLAT_SDK700_MHU0_SEND + CPU_INTR_S_STAT) == 0); 117 } 118