1 /* 2 * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 9 #include <platform_def.h> 10 11 #include <arch_helpers.h> 12 #include <drivers/arm/css/css_mhu.h> 13 #include <lib/bakery_lock.h> 14 #include <lib/mmio.h> 15 #include <plat/arm/common/plat_arm.h> 16 17 /* SCP MHU secure channel registers */ 18 #define SCP_INTR_S_STAT 0x200 19 #define SCP_INTR_S_SET 0x208 20 #define SCP_INTR_S_CLEAR 0x210 21 22 /* CPU MHU secure channel registers */ 23 #define CPU_INTR_S_STAT 0x300 24 #define CPU_INTR_S_SET 0x308 25 #define CPU_INTR_S_CLEAR 0x310 26 27 ARM_INSTANTIATE_LOCK; 28 29 /* Weak definition may be overridden in specific CSS based platform */ 30 #pragma weak plat_arm_pwrc_setup 31 32 33 /* 34 * Slot 31 is reserved because the MHU hardware uses this register bit to 35 * indicate a non-secure access attempt. The total number of available slots is 36 * therefore 31 [30:0]. 37 */ 38 #define MHU_MAX_SLOT_ID 30 39 mhu_secure_message_start(unsigned int slot_id)40void mhu_secure_message_start(unsigned int slot_id) 41 { 42 assert(slot_id <= MHU_MAX_SLOT_ID); 43 44 arm_lock_get(); 45 46 /* Make sure any previous command has finished */ 47 while (mmio_read_32(PLAT_CSS_MHU_BASE + CPU_INTR_S_STAT) & 48 (1 << slot_id)) 49 ; 50 } 51 mhu_secure_message_send(unsigned int slot_id)52void mhu_secure_message_send(unsigned int slot_id) 53 { 54 assert(slot_id <= MHU_MAX_SLOT_ID); 55 assert(!(mmio_read_32(PLAT_CSS_MHU_BASE + CPU_INTR_S_STAT) & 56 (1 << slot_id))); 57 58 /* Send command to SCP */ 59 mmio_write_32(PLAT_CSS_MHU_BASE + CPU_INTR_S_SET, 1 << slot_id); 60 } 61 mhu_secure_message_wait(void)62uint32_t mhu_secure_message_wait(void) 63 { 64 /* Wait for response from SCP */ 65 uint32_t response; 66 while (!(response = mmio_read_32(PLAT_CSS_MHU_BASE + SCP_INTR_S_STAT))) 67 ; 68 69 return response; 70 } 71 mhu_secure_message_end(unsigned int slot_id)72void mhu_secure_message_end(unsigned int slot_id) 73 { 74 assert(slot_id <= MHU_MAX_SLOT_ID); 75 76 /* 77 * Clear any response we got by writing one in the relevant slot bit to 78 * the CLEAR register 79 */ 80 mmio_write_32(PLAT_CSS_MHU_BASE + SCP_INTR_S_CLEAR, 1 << slot_id); 81 82 arm_lock_release(); 83 } 84 mhu_secure_init(void)85void __init mhu_secure_init(void) 86 { 87 arm_lock_init(); 88 89 /* 90 * The STAT register resets to zero. Ensure it is in the expected state, 91 * as a stale or garbage value would make us think it's a message we've 92 * already sent. 93 */ 94 assert(mmio_read_32(PLAT_CSS_MHU_BASE + CPU_INTR_S_STAT) == 0); 95 } 96 plat_arm_pwrc_setup(void)97void __init plat_arm_pwrc_setup(void) 98 { 99 mhu_secure_init(); 100 } 101