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