blob: 2231d1173454cb316c4fcd02f471e0b032e5c003 [file] [log] [blame]
Khandelwal368564c2020-01-29 16:51:42 +00001/*
2 * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8
9#include <arch_helpers.h>
10#include <common/debug.h>
11#include <drivers/delay_timer.h>
12#include <lib/bakery_lock.h>
13#include <lib/mmio.h>
14
15#include "mhu.h"
16#include <plat_arm.h>
17#include <platform_def.h>
18
19ARM_INSTANTIATE_LOCK;
20
21#pragma weak plat_arm_pwrc_setup
22
23/*
24 * Slot 31 is reserved because the MHU hardware uses this register bit to
25 * indicate a non-secure access attempt. The total number of available slots is
26 * therefore 31 [30:0].
27 */
28#define MHU_MAX_SLOT_ID 30
29
30void mhu_secure_message_start(uintptr_t address, unsigned int slot_id)
31{
32 unsigned int intr_stat_check;
33 uint64_t timeout_cnt;
34 volatile uint8_t expiration;
35
36 assert(slot_id <= MHU_MAX_SLOT_ID);
37 arm_lock_get();
38
39 /*
40 * Make sure any previous command has finished
41 * and polling timeout not expired
42 */
43
44 timeout_cnt = timeout_init_us(MHU_POLL_INTR_STAT_TIMEOUT);
45
46 do {
47 intr_stat_check = (mmio_read_32(address + CPU_INTR_S_STAT) &
48 (1 << slot_id));
49
50 expiration = timeout_elapsed(timeout_cnt);
51
52 } while ((intr_stat_check != 0U) && (expiration == 0U));
53
54 /*
55 * Note: No risk of timer overflows while waiting
56 * for the timeout expiration.
57 * According to Armv8 TRM: System counter roll-over
58 * time of not less than 40 years
59 */
60}
61
62void mhu_secure_message_send(uintptr_t address,
63 unsigned int slot_id,
64 unsigned int message)
65{
66 unsigned char access_ready;
67 uint64_t timeout_cnt;
68 volatile uint8_t expiration;
69
70 assert(slot_id <= MHU_MAX_SLOT_ID);
71 assert((mmio_read_32(address + CPU_INTR_S_STAT) &
72 (1 << slot_id)) == 0U);
73
74 MHU_V2_ACCESS_REQUEST(address);
75
76 timeout_cnt = timeout_init_us(MHU_POLL_INTR_STAT_TIMEOUT);
77
78 do {
79 access_ready = MHU_V2_IS_ACCESS_READY(address);
80 expiration = timeout_elapsed(timeout_cnt);
81
82 } while ((access_ready == 0U) && (expiration == 0U));
83
84 /*
85 * Note: No risk of timer overflows while waiting
86 * for the timeout expiration.
87 * According to Armv8 TRM: System counter roll-over
88 * time of not less than 40 years
89 */
90
91 mmio_write_32(address + CPU_INTR_S_SET, message);
92}
93
94void mhu_secure_message_end(uintptr_t address, unsigned int slot_id)
95{
96 assert(slot_id <= MHU_MAX_SLOT_ID);
97 /*
98 * Clear any response we got by writing one in the relevant slot bit to
99 * the CLEAR register
100 */
101 MHU_V2_CLEAR_REQUEST(address);
102
103 arm_lock_release();
104}
105
106void __init mhu_secure_init(void)
107{
108 arm_lock_init();
109
110 /*
111 * The STAT register resets to zero. Ensure it is in the expected state,
112 * as a stale or garbage value would make us think it's a message we've
113 * already sent.
114 */
115
116 assert(mmio_read_32(PLAT_SDK700_MHU0_SEND + CPU_INTR_S_STAT) == 0);
117}