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