xref: /rk3399_ARM-atf/plat/socionext/synquacer/drivers/mhu/sq_mhu.c (revision 09d40e0e08283a249e7dce0e106c07c5141f9b7e)
105377100SSumit Garg /*
205377100SSumit Garg  * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
305377100SSumit Garg  *
405377100SSumit Garg  * SPDX-License-Identifier: BSD-3-Clause
505377100SSumit Garg  */
605377100SSumit Garg 
705377100SSumit Garg #include <assert.h>
8*09d40e0eSAntonio Nino Diaz 
905377100SSumit Garg #include <platform_def.h>
10*09d40e0eSAntonio Nino Diaz 
11*09d40e0eSAntonio Nino Diaz #include <arch_helpers.h>
12*09d40e0eSAntonio Nino Diaz #include <lib/bakery_lock.h>
13*09d40e0eSAntonio Nino Diaz #include <lib/mmio.h>
14*09d40e0eSAntonio Nino Diaz 
1505377100SSumit Garg #include <sq_common.h>
1605377100SSumit Garg #include "sq_mhu.h"
1705377100SSumit Garg 
1805377100SSumit Garg /* SCP MHU secure channel registers */
1905377100SSumit Garg #define SCP_INTR_S_STAT		0x200
2005377100SSumit Garg #define SCP_INTR_S_SET		0x208
2105377100SSumit Garg #define SCP_INTR_S_CLEAR	0x210
2205377100SSumit Garg 
2305377100SSumit Garg /* CPU MHU secure channel registers */
2405377100SSumit Garg #define CPU_INTR_S_STAT		0x300
2505377100SSumit Garg #define CPU_INTR_S_SET		0x308
2605377100SSumit Garg #define CPU_INTR_S_CLEAR	0x310
2705377100SSumit Garg 
2805377100SSumit Garg DEFINE_BAKERY_LOCK(sq_lock);
2905377100SSumit Garg 
3005377100SSumit Garg /*
3105377100SSumit Garg  * Slot 31 is reserved because the MHU hardware uses this register bit to
3205377100SSumit Garg  * indicate a non-secure access attempt. The total number of available slots is
3305377100SSumit Garg  * therefore 31 [30:0].
3405377100SSumit Garg  */
3505377100SSumit Garg #define MHU_MAX_SLOT_ID		30
3605377100SSumit Garg 
3705377100SSumit Garg void mhu_secure_message_start(unsigned int slot_id)
3805377100SSumit Garg {
3905377100SSumit Garg 	assert(slot_id <= MHU_MAX_SLOT_ID);
4005377100SSumit Garg 
4105377100SSumit Garg 	bakery_lock_get(&sq_lock);
4205377100SSumit Garg 
4305377100SSumit Garg 	/* Make sure any previous command has finished */
4405377100SSumit Garg 	while (mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) &
4505377100SSumit Garg 							(1 << slot_id))
4605377100SSumit Garg 		;
4705377100SSumit Garg }
4805377100SSumit Garg 
4905377100SSumit Garg void mhu_secure_message_send(unsigned int slot_id)
5005377100SSumit Garg {
5105377100SSumit Garg 	assert(slot_id <= MHU_MAX_SLOT_ID);
5205377100SSumit Garg 	assert(!(mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) &
5305377100SSumit Garg 							(1 << slot_id)));
5405377100SSumit Garg 
5505377100SSumit Garg 	/* Send command to SCP */
5605377100SSumit Garg 	mmio_write_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_SET, 1 << slot_id);
5705377100SSumit Garg }
5805377100SSumit Garg 
5905377100SSumit Garg uint32_t mhu_secure_message_wait(void)
6005377100SSumit Garg {
6105377100SSumit Garg 	uint32_t response;
6205377100SSumit Garg 
6305377100SSumit Garg 	/* Wait for response from SCP */
6405377100SSumit Garg 	while (!(response = mmio_read_32(PLAT_SQ_MHU_BASE + SCP_INTR_S_STAT)))
6505377100SSumit Garg 		;
6605377100SSumit Garg 
6705377100SSumit Garg 	return response;
6805377100SSumit Garg }
6905377100SSumit Garg 
7005377100SSumit Garg void mhu_secure_message_end(unsigned int slot_id)
7105377100SSumit Garg {
7205377100SSumit Garg 	assert(slot_id <= MHU_MAX_SLOT_ID);
7305377100SSumit Garg 
7405377100SSumit Garg 	/*
7505377100SSumit Garg 	 * Clear any response we got by writing one in the relevant slot bit to
7605377100SSumit Garg 	 * the CLEAR register
7705377100SSumit Garg 	 */
7805377100SSumit Garg 	mmio_write_32(PLAT_SQ_MHU_BASE + SCP_INTR_S_CLEAR, 1 << slot_id);
7905377100SSumit Garg 
8005377100SSumit Garg 	bakery_lock_release(&sq_lock);
8105377100SSumit Garg }
8205377100SSumit Garg 
8305377100SSumit Garg void mhu_secure_init(void)
8405377100SSumit Garg {
8505377100SSumit Garg 	bakery_lock_init(&sq_lock);
8605377100SSumit Garg 
8705377100SSumit Garg 	/*
8805377100SSumit Garg 	 * The STAT register resets to zero. Ensure it is in the expected state,
8905377100SSumit Garg 	 * as a stale or garbage value would make us think it's a message we've
9005377100SSumit Garg 	 * already sent.
9105377100SSumit Garg 	 */
9205377100SSumit Garg 	assert(mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) == 0);
9305377100SSumit Garg }
9405377100SSumit Garg 
9505377100SSumit Garg void plat_sq_pwrc_setup(void)
9605377100SSumit Garg {
9705377100SSumit Garg 	mhu_secure_init();
9805377100SSumit Garg }
99