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