1 /*
2  * Copyright (c) 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 <lib/bakery_lock.h>
13 #include <lib/mmio.h>
14 
15 #include <sq_common.h>
16 #include "sq_mhu.h"
17 
18 /* SCP MHU secure channel registers */
19 #define SCP_INTR_S_STAT		0x200
20 #define SCP_INTR_S_SET		0x208
21 #define SCP_INTR_S_CLEAR	0x210
22 
23 /* CPU MHU secure channel registers */
24 #define CPU_INTR_S_STAT		0x300
25 #define CPU_INTR_S_SET		0x308
26 #define CPU_INTR_S_CLEAR	0x310
27 
28 DEFINE_BAKERY_LOCK(sq_lock);
29 
30 /*
31  * Slot 31 is reserved because the MHU hardware uses this register bit to
32  * indicate a non-secure access attempt. The total number of available slots is
33  * therefore 31 [30:0].
34  */
35 #define MHU_MAX_SLOT_ID		30
36 
mhu_secure_message_start(unsigned int slot_id)37 void mhu_secure_message_start(unsigned int slot_id)
38 {
39 	assert(slot_id <= MHU_MAX_SLOT_ID);
40 
41 	bakery_lock_get(&sq_lock);
42 
43 	/* Make sure any previous command has finished */
44 	while (mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) &
45 							(1 << slot_id))
46 		;
47 }
48 
mhu_secure_message_send(unsigned int slot_id)49 void mhu_secure_message_send(unsigned int slot_id)
50 {
51 	assert(slot_id <= MHU_MAX_SLOT_ID);
52 	assert(!(mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) &
53 							(1 << slot_id)));
54 
55 	/* Send command to SCP */
56 	mmio_write_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_SET, 1 << slot_id);
57 }
58 
mhu_secure_message_wait(void)59 uint32_t mhu_secure_message_wait(void)
60 {
61 	uint32_t response;
62 
63 	/* Wait for response from SCP */
64 	while (!(response = mmio_read_32(PLAT_SQ_MHU_BASE + SCP_INTR_S_STAT)))
65 		;
66 
67 	return response;
68 }
69 
mhu_secure_message_end(unsigned int slot_id)70 void mhu_secure_message_end(unsigned int slot_id)
71 {
72 	assert(slot_id <= MHU_MAX_SLOT_ID);
73 
74 	/*
75 	 * Clear any response we got by writing one in the relevant slot bit to
76 	 * the CLEAR register
77 	 */
78 	mmio_write_32(PLAT_SQ_MHU_BASE + SCP_INTR_S_CLEAR, 1 << slot_id);
79 
80 	bakery_lock_release(&sq_lock);
81 }
82 
mhu_secure_init(void)83 void mhu_secure_init(void)
84 {
85 	bakery_lock_init(&sq_lock);
86 
87 	/*
88 	 * The STAT register resets to zero. Ensure it is in the expected state,
89 	 * as a stale or garbage value would make us think it's a message we've
90 	 * already sent.
91 	 */
92 	assert(mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) == 0);
93 }
94 
plat_sq_pwrc_setup(void)95 void plat_sq_pwrc_setup(void)
96 {
97 	mhu_secure_init();
98 }
99