blob: 39edc9d1e39d93e86a65840dcdf30f8a70296142 [file] [log] [blame]
Patrick Williams975a06f2022-10-21 14:42:47 -05001From e4ccb92f8de94a82edd3548d62c853790ae36bd1 Mon Sep 17 00:00:00 2001
Brad Bishopbec4ebc2022-08-03 09:55:16 -04002From: Vishnu Banavath <vishnu.banavath@arm.com>
Patrick Williams975a06f2022-10-21 14:42:47 -05003Date: Fri, 3 Dec 2021 18:00:46 +0000
4Subject: [PATCH 02/19] Implement mhu driver and the OpenAmp conversion layer.
Brad Bishopbec4ebc2022-08-03 09:55:16 -04005
Patrick Williams975a06f2022-10-21 14:42:47 -05006This commit adds an mhu driver (v2.1 and v2) to the secure
7partition se_proxy and a conversion layer to communicate with
8the secure enclave using OpenAmp.
Brad Bishopbec4ebc2022-08-03 09:55:16 -04009
Patrick Williams975a06f2022-10-21 14:42:47 -050010Upstream-Status: Pending
Brad Bishopbec4ebc2022-08-03 09:55:16 -040011Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
Patrick Williams975a06f2022-10-21 14:42:47 -050012Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
Brad Bishopbec4ebc2022-08-03 09:55:16 -040013---
Patrick Williams975a06f2022-10-21 14:42:47 -050014 .../se-proxy/opteesp/default_se-proxy.dts.in | 16 +
Brad Bishopbec4ebc2022-08-03 09:55:16 -040015 .../drivers/arm/mhu_driver/component.cmake | 12 +
16 platform/drivers/arm/mhu_driver/mhu_v2.h | 391 ++++++++++++
17 platform/drivers/arm/mhu_driver/mhu_v2_x.c | 602 ++++++++++++++++++
Patrick Williams975a06f2022-10-21 14:42:47 -050018 .../providers/arm/corstone1000/platform.cmake | 10 +
19 5 files changed, 1031 insertions(+)
Brad Bishopbec4ebc2022-08-03 09:55:16 -040020 create mode 100644 platform/drivers/arm/mhu_driver/component.cmake
21 create mode 100644 platform/drivers/arm/mhu_driver/mhu_v2.h
22 create mode 100644 platform/drivers/arm/mhu_driver/mhu_v2_x.c
Patrick Williams975a06f2022-10-21 14:42:47 -050023 create mode 100644 platform/providers/arm/corstone1000/platform.cmake
Brad Bishopbec4ebc2022-08-03 09:55:16 -040024
Patrick Williams975a06f2022-10-21 14:42:47 -050025diff --git a/deployments/se-proxy/opteesp/default_se-proxy.dts.in b/deployments/se-proxy/opteesp/default_se-proxy.dts.in
26index 5748d2f80f88..267b4f923540 100644
27--- a/deployments/se-proxy/opteesp/default_se-proxy.dts.in
28+++ b/deployments/se-proxy/opteesp/default_se-proxy.dts.in
29@@ -17,4 +17,20 @@
30 xlat-granule = <0>; /* 4KiB */
31 messaging-method = <3>; /* Direct messaging only */
32 legacy-elf-format = <1>;
33+
34+ device-regions {
35+ compatible = "arm,ffa-manifest-device-regions";
36+ mhu-sender {
37+ /* Armv8 A Foundation Platform values */
38+ base-address = <0x00000000 0x1b820000>;
39+ pages-count = <16>;
40+ attributes = <0x3>; /* read-write */
41+ };
42+ mhu-receiver {
43+ /* Armv8 A Foundation Platform values */
44+ base-address = <0x00000000 0x1b830000>;
45+ pages-count = <16>;
46+ attributes = <0x3>; /* read-write */
47+ };
48+ };
49 };
Brad Bishopbec4ebc2022-08-03 09:55:16 -040050diff --git a/platform/drivers/arm/mhu_driver/component.cmake b/platform/drivers/arm/mhu_driver/component.cmake
51new file mode 100644
Patrick Williams975a06f2022-10-21 14:42:47 -050052index 000000000000..77a5a50b67d1
Brad Bishopbec4ebc2022-08-03 09:55:16 -040053--- /dev/null
54+++ b/platform/drivers/arm/mhu_driver/component.cmake
55@@ -0,0 +1,12 @@
56+#-------------------------------------------------------------------------------
57+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
58+#
59+# SPDX-License-Identifier: BSD-3-Clause
60+#
61+#-------------------------------------------------------------------------------
62+
63+# Add source files for using mhu driver
64+target_sources(${TGT}
65+ PRIVATE
66+ "${CMAKE_CURRENT_LIST_DIR}/mhu_v2_x.c"
67+)
68diff --git a/platform/drivers/arm/mhu_driver/mhu_v2.h b/platform/drivers/arm/mhu_driver/mhu_v2.h
69new file mode 100644
Patrick Williams975a06f2022-10-21 14:42:47 -050070index 000000000000..2e4ba80fab95
Brad Bishopbec4ebc2022-08-03 09:55:16 -040071--- /dev/null
72+++ b/platform/drivers/arm/mhu_driver/mhu_v2.h
73@@ -0,0 +1,391 @@
74+/*
75+ * Copyright (c) 2021 Arm Limited
76+ *
77+ * Licensed under the Apache License, Version 2.0 (the "License");
78+ * you may not use this file except in compliance with the License.
79+ * You may obtain a copy of the License at
80+ *
81+ * http://www.apache.org/licenses/LICENSE-2.0
82+ *
83+ * Unless required by applicable law or agreed to in writing, software
84+ * distributed under the License is distributed on an "AS IS" BASIS,
85+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
86+ * See the License for the specific language governing permissions and
87+ * limitations under the License.
88+ */
89+
90+/**
91+ * \file mhu_v2_x.h
92+ * \brief Driver for Arm MHU v2.0 and v2.1
93+ */
94+
95+#ifndef __MHU_V2_X_H__
96+#define __MHU_V2_X_H__
97+
98+#include <stdint.h>
99+#include <stdbool.h>
100+
101+#ifdef __cplusplus
102+extern "C" {
103+#endif
104+
105+#define MHU_2_X_INTR_NR2R_OFF (0x0u)
106+#define MHU_2_X_INTR_R2NR_OFF (0x1u)
107+#define MHU_2_1_INTR_CHCOMB_OFF (0x2u)
108+
109+#define MHU_2_X_INTR_NR2R_MASK (0x1u << MHU_2_X_INTR_NR2R_OFF)
110+#define MHU_2_X_INTR_R2NR_MASK (0x1u << MHU_2_X_INTR_R2NR_OFF)
111+#define MHU_2_1_INTR_CHCOMB_MASK (0x1u << MHU_2_1_INTR_CHCOMB_OFF)
112+
113+enum mhu_v2_x_frame_t {
114+ MHU_V2_X_SENDER_FRAME = 0x0u,
115+ MHU_V2_X_RECEIVER_FRAME = 0x1u,
116+};
117+
118+enum mhu_v2_x_supported_revisions {
119+ MHU_REV_READ_FROM_HW = 0,
120+ MHU_REV_2_0,
121+ MHU_REV_2_1,
122+};
123+
124+struct mhu_v2_x_dev_t {
125+ uint32_t base;
126+ enum mhu_v2_x_frame_t frame;
127+ uint32_t subversion; /*!< Hardware subversion: v2.X */
128+ bool is_initialized; /*!< Indicates if the MHU driver
129+ * is initialized and enabled
130+ */
131+};
132+
133+/**
134+ * \brief MHU v2 error enumeration types.
135+ */
136+enum mhu_v2_x_error_t {
137+ MHU_V_2_X_ERR_NONE = 0,
138+ MHU_V_2_X_ERR_NOT_INIT = -1,
139+ MHU_V_2_X_ERR_ALREADY_INIT = -2,
140+ MHU_V_2_X_ERR_UNSUPPORTED_VERSION = -3,
141+ MHU_V_2_X_ERR_INVALID_ARG = -4,
142+ MHU_V_2_X_ERR_GENERAL = -5
143+};
144+
145+/**
146+ * \brief Initializes the driver
147+ *
148+ * \param[in] dev MHU device struct \ref mhu_v2_x_dev_t
149+ * \param[in] rev MHU revision (if can't be identified from HW)
150+ *
151+ * Reads the MHU hardware version
152+ *
153+ * \return Returns mhu_v2_x_error_t error code
154+ *
155+ * \note MHU revision only has to be specified when versions can't be read
156+ * from HW (ARCH_MAJOR_REV reg reads as 0x0).
157+ *
158+ * \note This function doesn't check if dev is NULL.
159+ */
160+enum mhu_v2_x_error_t mhu_v2_x_driver_init(struct mhu_v2_x_dev_t *dev,
161+ enum mhu_v2_x_supported_revisions rev);
162+
163+/**
164+ * \brief Returns the number of channels implemented.
165+ *
166+ * \param[in] dev MHU device struct \ref mhu_v2_x_dev_t
167+ *
168+ * Returns the number of channels implemented.
169+ *
170+ * \return Returns the number of channels implemented.
171+ *
172+ * \note This function doesn't check if dev is NULL.
173+ */
174+uint32_t mhu_v2_x_get_num_channel_implemented(
175+ const struct mhu_v2_x_dev_t *dev);
176+
177+/**
178+ * \brief Sends the value over a channel.
179+ *
180+ * \param[in] dev MHU device struct \ref mhu_v2_x_dev_t
181+ * \param[in] channel Channel to send the value over.
182+ * \param[in] val Value to send.
183+ *
184+ * Sends the value over a channel.
185+ *
186+ * \return Returns mhu_v2_x_error_t error code
187+ *
188+ * \note This function doesn't check if dev is NULL.
189+ * \note This function doesn't check if channel is implemented.
190+ */
191+enum mhu_v2_x_error_t mhu_v2_x_channel_send(const struct mhu_v2_x_dev_t *dev,
192+ uint32_t channel, uint32_t val);
193+
194+/**
195+ * \brief Clears the channel after the value is send over it.
196+ *
197+ * \param[in] dev MHU device struct \ref mhu_v2_x_dev_t
198+ * \param[in] channel Channel to clear.
199+ *
200+ * Clears the channel after the value is send over it.
201+ *
202+ * \return Returns mhu_v2_x_error_t error code
203+ *
204+ * \note This function doesn't check if dev is NULL.
205+ * \note This function doesn't check if channel is implemented.
206+ */
207+enum mhu_v2_x_error_t mhu_v2_x_channel_clear(const struct mhu_v2_x_dev_t *dev,
208+ uint32_t channel);
209+
210+/**
211+ * \brief Receives the value over a channel.
212+ *
213+ * \param[in] dev MHU device struct \ref mhu_v2_x_dev_t
214+ * \param[in] channel Channel to receive the value from.
215+ * \param[out] value Pointer to variable that will store the value.
216+ *
217+ * Receives the value over a channel.
218+ *
219+ * \return Returns mhu_v2_x_error_t error code
220+ *
221+ * \note This function doesn't check if dev is NULL.
222+ * \note This function doesn't check if channel is implemented.
223+ */
224+enum mhu_v2_x_error_t mhu_v2_x_channel_receive(
225+ const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t *value);
226+
227+/**
228+ * \brief Sets bits in the Channel Mask.
229+ *
230+ * \param[in] dev MHU device struct \ref mhu_v2_x_dev_t
231+ * \param[in] channel Which channel's mask to set.
232+ * \param[in] mask Mask to be set over a receiver frame.
233+ *
234+ * Sets bits in the Channel Mask.
235+ *
236+ * \return Returns mhu_v2_x_error_t error code
237+ *
238+ * \note This function doesn't check if dev is NULL.
239+ * \note This function doesn't check if channel is implemented.
240+ */
241+enum mhu_v2_x_error_t mhu_v2_x_channel_mask_set(
242+ const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t mask);
243+
244+/**
245+ * \brief Clears bits in the Channel Mask.
246+ *
247+ * \param[in] dev MHU device struct \ref mhu_v2_x_dev_t
248+ * \param[in] channel Which channel's mask to clear.
249+ * \param[in] mask Mask to be clear over a receiver frame.
250+ *
251+ * Clears bits in the Channel Mask.
252+ *
253+ * \return Returns mhu_v2_x_error_t error code
254+ *
255+ * \note This function doesn't check if dev is NULL.
256+ * \note This function doesn't check if channel is implemented.
257+ */
258+enum mhu_v2_x_error_t mhu_v2_x_channel_mask_clear(
259+ const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t mask);
260+
261+/**
262+ * \brief Enables the Channel interrupt.
263+ *
264+ * \param[in] dev MHU device struct \ref mhu_v2_x_dev_t
265+ * \param[in] channel Which channel's interrupt to enable.
266+ *
267+ * Enables the Channel clear interrupt.
268+ *
269+ * \return Returns mhu_v2_x_error_t error code
270+ *
271+ * \note This function doesn't check if dev is NULL.
272+ * \note This function doesn't check if channel is implemented.
273+ */
274+enum mhu_v2_x_error_t mhu_v2_x_channel_interrupt_enable(
275+ const struct mhu_v2_x_dev_t *dev, uint32_t channel);
276+
277+/**
278+ * \brief Disables the Channel interrupt.
279+ *
280+ * \param[in] dev MHU device struct \ref mhu_v2_x_dev_t
281+ * \param[in] channel Which channel's interrupt to disable.
282+ *
283+ * Disables the Channel interrupt.
284+ *
285+ * \return Returns mhu_v2_x_error_t error code
286+ *
287+ * \note This function doesn't check if dev is NULL.
288+ * \note This function doesn't check if channel is implemented.
289+ */
290+enum mhu_v2_x_error_t mhu_v2_x_channel_interrupt_disable(
291+ const struct mhu_v2_x_dev_t *dev, uint32_t channel);
292+
293+/**
294+ * \brief Cleares the Channel interrupt.
295+ *
296+ * \param[in] dev MHU device struct \ref mhu_v2_x_dev_t
297+ * \param[in] channel Which channel's interrupt to clear.
298+ *
299+ * Cleares the Channel interrupt.
300+ *
301+ * \return Returns mhu_v2_x_error_t error code
302+ *
303+ * \note This function doesn't check if dev is NULL.
304+ * \note This function doesn't check if channel is implemented.
305+ */
306+enum mhu_v2_x_error_t mhu_v2_x_channel_interrupt_clear(
307+ const struct mhu_v2_x_dev_t *dev, uint32_t channel);
308+
309+/**
310+ * \brief Initiates a MHU transfer with the handshake signals.
311+ *
312+ * \param[in] dev MHU device struct \ref mhu_v2_x_dev_t
313+ *
314+ * Initiates a MHU transfer with the handshake signals in a blocking mode.
315+ *
316+ * \return Returns mhu_v2_x_error_t error code
317+ *
318+ * \note This function doesn't check if dev is NULL.
319+ */
320+enum mhu_v2_x_error_t mhu_v2_x_initiate_transfer(
321+ const struct mhu_v2_x_dev_t *dev);
322+
323+/**
324+ * \brief Closes a MHU transfer with the handshake signals.
325+ *
326+ * \param[in] dev MHU device struct \ref mhu_v2_x_dev_t
327+ *
328+ * Closes a MHU transfer with the handshake signals in a blocking mode.
329+ *
330+ * \return Returns mhu_v2_x_error_t error code
331+ *
332+ * \note This function doesn't check if dev is NULL.
333+ */
334+enum mhu_v2_x_error_t mhu_v2_x_close_transfer(
335+ const struct mhu_v2_x_dev_t *dev);
336+
337+/**
338+ * \brief Returns the value of access request signal.
339+ *
340+ * \param[in] dev MHU device struct \ref mhu_v2_x_dev_t
341+ * \param[out] val Pointer to variable that will store the value.
342+ *
343+ * For more information please read the MHU v2 user guide
344+ *
345+ * \return Returns mhu_v2_x_error_t error code
346+ *
347+ * \note This function doesn't check if dev is NULL.
348+ */
349+enum mhu_v2_x_error_t mhu_v2_x_get_access_request(
350+ const struct mhu_v2_x_dev_t *dev, uint32_t *val);
351+
352+/**
353+ * \brief Sets the value of access request signal to high.
354+ *
355+ * \param[in] dev MHU device struct \ref mhu_v2_x_dev_t
356+ *
357+ * For more information please read the MHU v2 user guide
358+ *
359+ * \return Returns mhu_v2_x_error_t error code
360+ *
361+ * \note This function doesn't check if dev is NULL.
362+ */
363+enum mhu_v2_x_error_t mhu_v2_x_set_access_request(
364+ const struct mhu_v2_x_dev_t *dev);
365+
366+/**
367+ * \brief Sets the value of access request signal to low.
368+ *
369+ * \param[in] dev MHU device struct \ref mhu_v2_x_dev_t
370+ *
371+ * For more information please read the MHU v2 user guide
372+ *
373+ * \return Returns mhu_v2_x_error_t error code
374+ *
375+ * \note This function doesn't check if dev is NULL.
376+ */
377+enum mhu_v2_x_error_t mhu_v2_x_reset_access_request(
378+ const struct mhu_v2_x_dev_t *dev);
379+
380+/**
381+ * \brief Returns the value of access ready signal.
382+ *
383+ * \param[in] dev MHU device struct \ref mhu_v2_x_dev_t
384+ * \param[out] val Pointer to variable that will store the value.
385+ *
386+ * For more information please read the MHU v2 user guide
387+ *
388+ * \return Returns mhu_v2_x_error_t error code
389+ *
390+ * \note This function doesn't check if dev is NULL.
391+ */
392+enum mhu_v2_x_error_t mhu_v2_x_get_access_ready(
393+ const struct mhu_v2_x_dev_t *dev, uint32_t *val);
394+
395+/**
396+ * \brief Returns the MHU interrupt status.
397+ *
398+ * \param[in] dev MHU device struct \ref mhu_v2_x_dev_t
399+ *
400+ * \return Interrupt status register value. Masking is needed for individual
401+ * interrupts.
402+ *
403+ * \note This function doesn't check if dev is NULL.
404+ */
405+uint32_t mhu_v2_x_get_interrupt_status(const struct mhu_v2_x_dev_t *dev);
406+
407+/**
408+ * \brief Enables MHU interrupts.
409+ *
410+ * \param[in] dev MHU device struct \ref mhu_v2_x_dev_t
411+ * \param[in] mask Bit mask for enabling/disabling interrupts
412+ *
413+ * \return Returns mhu_v2_x_error_t error code
414+ *
415+ * \note This function doesn't check if dev is NULL.
416+ */
417+enum mhu_v2_x_error_t mhu_v2_x_interrupt_enable(
418+ const struct mhu_v2_x_dev_t *dev, uint32_t mask);
419+
420+/**
421+ * \brief Disables MHU interrupts.
422+ *
423+ * \param[in] dev MHU device struct \ref mhu_v2_x_dev_t
424+ * \param[in] mask Bit mask for enabling/disabling interrupts
425+ *
426+ * \return Returns mhu_v2_x_error_t error code
427+ *
428+ * \note This function doesn't check if dev is NULL.
429+ */
430+enum mhu_v2_x_error_t mhu_v2_x_interrupt_disable(
431+ const struct mhu_v2_x_dev_t *dev, uint32_t mask);
432+
433+/**
434+ * \brief Clears MHU interrupts.
435+ *
436+ * \param[in] dev MHU device struct \ref mhu_v2_x_dev_t
437+ * \param[in] mask Bit mask for clearing interrupts
438+ *
439+ * \return Returns mhu_v2_x_error_t error code
440+ *
441+ * \note This function doesn't check if dev is NULL.
442+ */
443+enum mhu_v2_x_error_t mhu_v2_x_interrupt_clear(
444+ const struct mhu_v2_x_dev_t *dev, uint32_t mask);
445+
446+/**
447+ * \brief Returns the first channel number whose interrupt bit is high.
448+ *
449+ * \param[in] dev MHU device struct \ref mhu_v2_x_dev_t
450+ * \param[out] channel Pointer to variable that will have the channel value.
451+ *
452+ * \return Returns the first channel number whose interrupt bit is high.
453+ * \return Returns mhu_v2_x_error_t error code.
454+ *
455+ * \note This function doesn't check if dev is NULL.
456+ */
457+enum mhu_v2_x_error_t mhu_v2_1_get_ch_interrupt_num(
458+ const struct mhu_v2_x_dev_t *dev, uint32_t *channel);
459+
460+#ifdef __cplusplus
461+}
462+#endif
463+
464+#endif /* __MHU_V2_X_H__ */
465diff --git a/platform/drivers/arm/mhu_driver/mhu_v2_x.c b/platform/drivers/arm/mhu_driver/mhu_v2_x.c
466new file mode 100644
Patrick Williams975a06f2022-10-21 14:42:47 -0500467index 000000000000..01d8f659a73a
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400468--- /dev/null
469+++ b/platform/drivers/arm/mhu_driver/mhu_v2_x.c
470@@ -0,0 +1,602 @@
471+/*
472+ * Copyright (c) 2021 Arm Limited
473+ *
474+ * Licensed under the Apache License, Version 2.0 (the "License");
475+ * you may not use this file except in compliance with the License.
476+ * You may obtain a copy of the License at
477+ *
478+ * http://www.apache.org/licenses/LICENSE-2.0
479+ *
480+ * Unless required by applicable law or agreed to in writing, software
481+ * distributed under the License is distributed on an "AS IS" BASIS,
482+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
483+ * See the License for the specific language governing permissions and
484+ * limitations under the License.
485+ */
486+#include <stdint.h>
487+#include <stdbool.h>
488+#include "mhu_v2.h"
489+
490+#define _MHU_V2_X_MAX_CHANNELS 124
491+#define _MHU_V2_1_MAX_CHCOMB_INT 4
492+#define ENABLE 0x1
493+#define DISABLE 0x0
494+#define CLEAR_INTR 0x1
495+#define CH_PER_CH_COMB 0x20
496+#define SEND_FRAME(p_mhu) ((struct _mhu_v2_x_send_frame_t *)p_mhu)
497+#define RECV_FRAME(p_mhu) ((struct _mhu_v2_x_recv_frame_t *)p_mhu)
498+
499+#define MHU_MAJOR_REV_V2 0x1u
500+#define MHU_MINOR_REV_2_0 0x0u
501+#define MHU_MINOR_REV_2_1 0x1u
502+
503+struct _mhu_v2_x_send_ch_window_t {
504+ /* Offset: 0x00 (R/ ) Channel Status */
505+ volatile uint32_t ch_st;
506+ /* Offset: 0x04 (R/ ) Reserved */
507+ volatile uint32_t reserved_0;
508+ /* Offset: 0x08 (R/ ) Reserved */
509+ volatile uint32_t reserved_1;
510+ /* Offset: 0x0C ( /W) Channel Set */
511+ volatile uint32_t ch_set;
512+ /* Offset: 0x10 (R/ ) Channel Interrupt Status (Reserved in 2.0) */
513+ volatile uint32_t ch_int_st;
514+ /* Offset: 0x14 ( /W) Channel Interrupt Clear (Reserved in 2.0) */
515+ volatile uint32_t ch_int_clr;
516+ /* Offset: 0x18 (R/W) Channel Interrupt Enable (Reserved in 2.0) */
517+ volatile uint32_t ch_int_en;
518+ /* Offset: 0x1C (R/ ) Reserved */
519+ volatile uint32_t reserved_2;
520+};
521+
522+struct _mhu_v2_x_send_frame_t {
523+ /* Offset: 0x000 ( / ) Sender Channel Window 0 -123 */
524+ struct _mhu_v2_x_send_ch_window_t send_ch_window[_MHU_V2_X_MAX_CHANNELS];
525+ /* Offset: 0xF80 (R/ ) Message Handling Unit Configuration */
526+ volatile uint32_t mhu_cfg;
527+ /* Offset: 0xF84 (R/W) Response Configuration */
528+ volatile uint32_t resp_cfg;
529+ /* Offset: 0xF88 (R/W) Access Request */
530+ volatile uint32_t access_request;
531+ /* Offset: 0xF8C (R/ ) Access Ready */
532+ volatile uint32_t access_ready;
533+ /* Offset: 0xF90 (R/ ) Interrupt Status */
534+ volatile uint32_t int_st;
535+ /* Offset: 0xF94 ( /W) Interrupt Clear */
536+ volatile uint32_t int_clr;
537+ /* Offset: 0xF98 (R/W) Interrupt Enable */
538+ volatile uint32_t int_en;
539+ /* Offset: 0xF9C (R/ ) Reserved */
540+ volatile uint32_t reserved_0;
541+ /* Offset: 0xFA0 (R/W) Channel Combined Interrupt Stat (Reserved in 2.0) */
542+ volatile uint32_t ch_comb_int_st[_MHU_V2_1_MAX_CHCOMB_INT];
543+ /* Offset: ‭0xFC4‬ (R/ ) Reserved */
544+ volatile uint32_t reserved_1[6];
545+ /* Offset: 0xFC8 (R/ ) Implementer Identification Register */
546+ volatile uint32_t iidr;
547+ /* Offset: 0xFCC (R/ ) Architecture Identification Register */
548+ volatile uint32_t aidr;
549+ /* Offset: 0xFD0 (R/ ) */
550+ volatile uint32_t pid_1[4];
551+ /* Offset: 0xFE0 (R/ ) */
552+ volatile uint32_t pid_0[4];
553+ /* Offset: 0xFF0 (R/ ) */
554+ volatile uint32_t cid[4];
555+};
556+
557+struct _mhu_v2_x_rec_ch_window_t {
558+ /* Offset: 0x00 (R/ ) Channel Status */
559+ volatile uint32_t ch_st;
560+ /* Offset: 0x04 (R/ ) Channel Status Masked */
561+ volatile uint32_t ch_st_msk;
562+ /* Offset: 0x08 ( /W) Channel Clear */
563+ volatile uint32_t ch_clr;
564+ /* Offset: 0x0C (R/ ) Reserved */
565+ volatile uint32_t reserved_0;
566+ /* Offset: 0x10 (R/ ) Channel Mask Status */
567+ volatile uint32_t ch_msk_st;
568+ /* Offset: 0x14 ( /W) Channel Mask Set */
569+ volatile uint32_t ch_msk_set;
570+ /* Offset: 0x18 ( /W) Channel Mask Clear */
571+ volatile uint32_t ch_msk_clr;
572+ /* Offset: 0x1C (R/ ) Reserved */
573+ volatile uint32_t reserved_1;
574+};
575+
576+struct _mhu_v2_x_recv_frame_t {
577+ /* Offset: 0x000 ( / ) Receiver Channel Window 0 -123 */
578+ struct _mhu_v2_x_rec_ch_window_t rec_ch_window[_MHU_V2_X_MAX_CHANNELS];
579+ /* Offset: 0xF80 (R/ ) Message Handling Unit Configuration */
580+ volatile uint32_t mhu_cfg;
581+ /* Offset: 0xF84 (R/ ) Reserved */
582+ volatile uint32_t reserved_0[3];
583+ /* Offset: 0xF90 (R/ ) Interrupt Status (Reserved in 2.0) */
584+ volatile uint32_t int_st;
585+ /* Offset: 0xF94 (R/ ) Interrupt Clear (Reserved in 2.0) */
586+ volatile uint32_t int_clr;
587+ /* Offset: 0xF98 (R/W) Interrupt Enable (Reserved in 2.0) */
588+ volatile uint32_t int_en;
589+ /* Offset: 0xF9C (R/ ) Reserved */
590+ volatile uint32_t reserved_1;
591+ /* Offset: 0xFA0 (R/ ) Channel Combined Interrupt Stat (Reserved in 2.0) */
592+ volatile uint32_t ch_comb_int_st[_MHU_V2_1_MAX_CHCOMB_INT];
593+ /* Offset: 0xFB0 (R/ ) Reserved */
594+ volatile uint32_t reserved_2[6];
595+ /* Offset: 0xFC8 (R/ ) Implementer Identification Register */
596+ volatile uint32_t iidr;
597+ /* Offset: 0xFCC (R/ ) Architecture Identification Register */
598+ volatile uint32_t aidr;
599+ /* Offset: 0xFD0 (R/ ) */
600+ volatile uint32_t pid_1[4];
601+ /* Offset: 0xFE0 (R/ ) */
602+ volatile uint32_t pid_0[4];
603+ /* Offset: 0xFF0 (R/ ) */
604+ volatile uint32_t cid[4];
605+};
606+
607+union _mhu_v2_x_frame_t {
608+ struct _mhu_v2_x_send_frame_t send_frame;
609+ struct _mhu_v2_x_recv_frame_t recv_frame;
610+};
611+
612+enum mhu_v2_x_error_t mhu_v2_x_driver_init(struct mhu_v2_x_dev_t *dev,
613+ enum mhu_v2_x_supported_revisions rev)
614+{
615+ uint32_t AIDR = 0;
616+ union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
617+
618+ if (dev->is_initialized) {
619+ return MHU_V_2_X_ERR_ALREADY_INIT;
620+ }
621+
622+ if (rev == MHU_REV_READ_FROM_HW) {
623+ /* Read revision from HW */
624+ if (dev->frame == MHU_V2_X_RECEIVER_FRAME) {
625+ AIDR = p_mhu->recv_frame.aidr;
626+ } else {
627+ AIDR = p_mhu->send_frame.aidr;
628+ }
629+
630+ /* Get bits 7:4 to read major revision */
631+ if ( ((AIDR >> 4) & 0b1111) != MHU_MAJOR_REV_V2) {
632+ /* Unsupported MHU version */
633+ return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
634+ } /* No need to save major version, driver only supports MHUv2 */
635+
636+ /* Get bits 3:0 to read minor revision */
637+ dev->subversion = AIDR & 0b1111;
638+
639+ if (dev->subversion != MHU_MINOR_REV_2_0 &&
640+ dev->subversion != MHU_MINOR_REV_2_1) {
641+ /* Unsupported subversion */
642+ return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
643+ }
644+ } else {
645+ /* Revisions were provided by caller */
646+ if (rev == MHU_REV_2_0) {
647+ dev->subversion = MHU_MINOR_REV_2_0;
648+ } else if (rev == MHU_REV_2_1) {
649+ dev->subversion = MHU_MINOR_REV_2_1;
650+ } else {
651+ /* Unsupported subversion */
652+ return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
653+ }/* No need to save major version, driver only supports MHUv2 */
654+ }
655+
656+ dev->is_initialized = true;
657+
658+ return MHU_V_2_X_ERR_NONE;
659+}
660+
661+uint32_t mhu_v2_x_get_num_channel_implemented(const struct mhu_v2_x_dev_t *dev)
662+{
663+ union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
664+
665+ if ( !(dev->is_initialized) ) {
666+ return MHU_V_2_X_ERR_NOT_INIT;
667+ }
668+
669+ if(dev->frame == MHU_V2_X_SENDER_FRAME) {
670+ return (SEND_FRAME(p_mhu))->mhu_cfg;
671+ } else {
672+ return (RECV_FRAME(p_mhu))->mhu_cfg;
673+ }
674+}
675+
676+enum mhu_v2_x_error_t mhu_v2_x_channel_send(const struct mhu_v2_x_dev_t *dev,
677+ uint32_t channel, uint32_t val)
678+{
679+ union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
680+
681+ if ( !(dev->is_initialized) ) {
682+ return MHU_V_2_X_ERR_NOT_INIT;
683+ }
684+
685+ if(dev->frame == MHU_V2_X_SENDER_FRAME) {
686+ (SEND_FRAME(p_mhu))->send_ch_window[channel].ch_set = val;
687+ return MHU_V_2_X_ERR_NONE;
688+ } else {
689+ return MHU_V_2_X_ERR_INVALID_ARG;
690+ }
691+}
692+
693+enum mhu_v2_x_error_t mhu_v2_x_channel_clear(const struct mhu_v2_x_dev_t *dev,
694+ uint32_t channel)
695+{
696+ union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
697+
698+ if ( !(dev->is_initialized) ) {
699+ return MHU_V_2_X_ERR_NOT_INIT;
700+ }
701+
702+ if(dev->frame == MHU_V2_X_RECEIVER_FRAME) {
703+ (RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_clr = UINT32_MAX;
704+ return MHU_V_2_X_ERR_NONE;
705+ } else {
706+ return MHU_V_2_X_ERR_INVALID_ARG;
707+ }
708+}
709+
710+enum mhu_v2_x_error_t mhu_v2_x_channel_receive(
711+ const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t *value)
712+{
713+ union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
714+
715+ if ( !(dev->is_initialized) ) {
716+ return MHU_V_2_X_ERR_NOT_INIT;
717+ }
718+
719+ if(dev->frame == MHU_V2_X_RECEIVER_FRAME) {
720+ *value = (RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_st;
721+ return MHU_V_2_X_ERR_NONE;
722+ } else {
723+ return MHU_V_2_X_ERR_INVALID_ARG;
724+ }
725+}
726+
727+enum mhu_v2_x_error_t mhu_v2_x_channel_mask_set(
728+ const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t mask)
729+{
730+ union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
731+
732+ if ( !(dev->is_initialized) ) {
733+ return MHU_V_2_X_ERR_NOT_INIT;
734+ }
735+
736+ if(dev->frame == MHU_V2_X_RECEIVER_FRAME) {
737+ (RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_msk_set = mask;
738+ return MHU_V_2_X_ERR_NONE;
739+ } else {
740+ return MHU_V_2_X_ERR_INVALID_ARG;
741+ }
742+}
743+
744+enum mhu_v2_x_error_t mhu_v2_x_channel_mask_clear(
745+ const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t mask)
746+{
747+ union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
748+
749+ if ( !(dev->is_initialized) ) {
750+ return MHU_V_2_X_ERR_NOT_INIT;
751+ }
752+
753+ if(dev->frame == MHU_V2_X_RECEIVER_FRAME) {
754+ (RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_msk_clr = mask;
755+ return MHU_V_2_X_ERR_NONE;
756+ } else {
757+ return MHU_V_2_X_ERR_INVALID_ARG;
758+ }
759+}
760+
761+enum mhu_v2_x_error_t mhu_v2_x_channel_interrupt_enable(
762+ const struct mhu_v2_x_dev_t *dev, uint32_t channel)
763+{
764+ union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
765+
766+ if ( !(dev->is_initialized) ) {
767+ return MHU_V_2_X_ERR_NOT_INIT;
768+ }
769+
770+ if (dev->subversion == MHU_MINOR_REV_2_1) {
771+ return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
772+ }
773+
774+ if(dev->frame == MHU_V2_X_SENDER_FRAME) {
775+ (SEND_FRAME(p_mhu))->send_ch_window[channel].ch_int_en = ENABLE;
776+ return MHU_V_2_X_ERR_NONE;
777+ } else {
778+ return MHU_V_2_X_ERR_INVALID_ARG;
779+ }
780+}
781+
782+enum mhu_v2_x_error_t mhu_v2_x_channel_interrupt_disable(
783+ const struct mhu_v2_x_dev_t *dev, uint32_t channel)
784+{
785+ union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
786+
787+ if ( !(dev->is_initialized) ) {
788+ return MHU_V_2_X_ERR_NOT_INIT;
789+ }
790+
791+ if (dev->subversion == MHU_MINOR_REV_2_1) {
792+ return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
793+ }
794+
795+ if(dev->frame == MHU_V2_X_SENDER_FRAME) {
796+ (SEND_FRAME(p_mhu))->send_ch_window[channel].ch_int_en = DISABLE;
797+ return MHU_V_2_X_ERR_NONE;
798+ } else {
799+ return MHU_V_2_X_ERR_INVALID_ARG;
800+ }
801+}
802+
803+enum mhu_v2_x_error_t mhu_v2_x_channel_interrupt_clear(
804+ const struct mhu_v2_x_dev_t *dev, uint32_t channel)
805+{
806+ union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
807+
808+ if ( !(dev->is_initialized) ) {
809+ return MHU_V_2_X_ERR_NOT_INIT;
810+ }
811+
812+ if (dev->subversion == MHU_MINOR_REV_2_1) {
813+ return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
814+ }
815+
816+ if(dev->frame == MHU_V2_X_SENDER_FRAME) {
817+ (SEND_FRAME(p_mhu))->send_ch_window[channel].ch_int_clr = CLEAR_INTR;
818+ return MHU_V_2_X_ERR_NONE;
819+ } else {
820+ return MHU_V_2_X_ERR_INVALID_ARG;
821+ }
822+}
823+
824+enum mhu_v2_x_error_t mhu_v2_x_initiate_transfer(
825+ const struct mhu_v2_x_dev_t *dev)
826+{
827+ union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
828+
829+ if ( !(dev->is_initialized) ) {
830+ return MHU_V_2_X_ERR_NOT_INIT;
831+ }
832+
833+ if(dev->frame != MHU_V2_X_SENDER_FRAME) {
834+ return MHU_V_2_X_ERR_INVALID_ARG;
835+ }
836+
837+ (SEND_FRAME(p_mhu))->access_request = ENABLE;
838+
839+ while ( !((SEND_FRAME(p_mhu))->access_ready) ) {
840+ /* Wait in a loop for access ready signal to be high */
841+ ;
842+ }
843+
844+ return MHU_V_2_X_ERR_NONE;
845+}
846+
847+enum mhu_v2_x_error_t mhu_v2_x_close_transfer(const struct mhu_v2_x_dev_t *dev)
848+{
849+ union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
850+
851+ if ( !(dev->is_initialized) ) {
852+ return MHU_V_2_X_ERR_NOT_INIT;
853+ }
854+
855+ if(dev->frame != MHU_V2_X_SENDER_FRAME) {
856+ return MHU_V_2_X_ERR_INVALID_ARG;
857+ }
858+
859+ (SEND_FRAME(p_mhu))->access_request = DISABLE;
860+
861+ return MHU_V_2_X_ERR_NONE;
862+}
863+
864+enum mhu_v2_x_error_t mhu_v2_x_get_access_request(
865+ const struct mhu_v2_x_dev_t *dev, uint32_t *val)
866+{
867+ union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
868+
869+ if ( !(dev->is_initialized) ) {
870+ return MHU_V_2_X_ERR_NOT_INIT;
871+ }
872+
873+ if(dev->frame != MHU_V2_X_SENDER_FRAME) {
874+ return MHU_V_2_X_ERR_INVALID_ARG;
875+ }
876+
877+ *val = (SEND_FRAME(p_mhu))->access_request;
878+
879+ return MHU_V_2_X_ERR_NONE;
880+}
881+
882+enum mhu_v2_x_error_t mhu_v2_x_set_access_request(
883+ const struct mhu_v2_x_dev_t *dev)
884+{
885+ union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
886+
887+ if ( !(dev->is_initialized) ) {
888+ return MHU_V_2_X_ERR_NOT_INIT;
889+ }
890+
891+ if(dev->frame != MHU_V2_X_SENDER_FRAME) {
892+ return MHU_V_2_X_ERR_INVALID_ARG;
893+ }
894+
895+ (SEND_FRAME(p_mhu))->access_request = ENABLE;
896+
897+ return MHU_V_2_X_ERR_NONE;
898+}
899+
900+enum mhu_v2_x_error_t mhu_v2_x_reset_access_request(
901+ const struct mhu_v2_x_dev_t *dev)
902+{
903+ union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
904+
905+ if ( !(dev->is_initialized) ) {
906+ return MHU_V_2_X_ERR_NOT_INIT;
907+ }
908+
909+ if(dev->frame != MHU_V2_X_SENDER_FRAME) {
910+ return MHU_V_2_X_ERR_INVALID_ARG;
911+ }
912+
913+ (SEND_FRAME(p_mhu))->access_request = DISABLE;
914+
915+ return MHU_V_2_X_ERR_NONE;
916+}
917+
918+enum mhu_v2_x_error_t mhu_v2_x_get_access_ready(
919+ const struct mhu_v2_x_dev_t *dev, uint32_t *val)
920+{
921+ union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
922+
923+ if ( !(dev->is_initialized) ) {
924+ return MHU_V_2_X_ERR_NOT_INIT;
925+ }
926+
927+ if(dev->frame != MHU_V2_X_SENDER_FRAME) {
928+ return MHU_V_2_X_ERR_INVALID_ARG;
929+ }
930+
931+ *val = (SEND_FRAME(p_mhu))->access_ready;
932+
933+ return MHU_V_2_X_ERR_NONE;
934+}
935+
936+uint32_t mhu_v2_x_get_interrupt_status(const struct mhu_v2_x_dev_t *dev)
937+{
938+ union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
939+
940+ if ( !(dev->is_initialized) ) {
941+ return MHU_V_2_X_ERR_NOT_INIT;
942+ }
943+
944+ if(dev->frame == MHU_V2_X_SENDER_FRAME) {
945+ return (SEND_FRAME(p_mhu))->int_st;
946+ } else {
947+ return (RECV_FRAME(p_mhu))->int_st;
948+ }
949+}
950+
951+enum mhu_v2_x_error_t mhu_v2_x_interrupt_enable(
952+ const struct mhu_v2_x_dev_t *dev, uint32_t mask)
953+{
954+ union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
955+
956+ if ( !(dev->is_initialized) ) {
957+ return MHU_V_2_X_ERR_NOT_INIT;
958+ }
959+
960+ if (dev->subversion == MHU_MINOR_REV_2_0) {
961+ if (mask & MHU_2_1_INTR_CHCOMB_MASK) {
962+ /* Combined channel IRQ is not present in v2.0 */
963+ return MHU_V_2_X_ERR_INVALID_ARG;
964+ }
965+
966+ if (dev->frame == MHU_V2_X_RECEIVER_FRAME) {
967+ /* Only sender frame has these registers */
968+ return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
969+ }
970+ }
971+
972+ if(dev->frame == MHU_V2_X_SENDER_FRAME) {
973+ (SEND_FRAME(p_mhu))->int_en |= mask;
974+ } else {
975+ (RECV_FRAME(p_mhu))->int_en |= mask;
976+ }
977+
978+ return MHU_V_2_X_ERR_NONE;
979+}
980+
981+enum mhu_v2_x_error_t mhu_v2_x_interrupt_disable(
982+ const struct mhu_v2_x_dev_t *dev, uint32_t mask)
983+{
984+ union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
985+
986+ if ( !(dev->is_initialized) ) {
987+ return MHU_V_2_X_ERR_NOT_INIT;
988+ }
989+
990+ if (dev->subversion == MHU_MINOR_REV_2_0) {
991+ if (mask & MHU_2_1_INTR_CHCOMB_MASK) {
992+ /* Combined channel IRQ is not present in v2.0 */
993+ return MHU_V_2_X_ERR_INVALID_ARG;
994+ }
995+
996+ if (dev->frame == MHU_V2_X_RECEIVER_FRAME) {
997+ /* Only sender frame has these registers */
998+ return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
999+ }
1000+ }
1001+
1002+ if(dev->frame == MHU_V2_X_SENDER_FRAME) {
1003+ (SEND_FRAME(p_mhu))->int_en &= ~mask;
1004+ } else {
1005+ (RECV_FRAME(p_mhu))->int_en &= ~mask;
1006+ }
1007+
1008+ return MHU_V_2_X_ERR_NONE;
1009+}
1010+
1011+enum mhu_v2_x_error_t mhu_v2_x_interrupt_clear(
1012+ const struct mhu_v2_x_dev_t *dev, uint32_t mask)
1013+{
1014+ union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
1015+
1016+ if ( !(dev->is_initialized) ) {
1017+ return MHU_V_2_X_ERR_NOT_INIT;
1018+ }
1019+
1020+ if (dev->subversion == MHU_MINOR_REV_2_0) {
1021+ if (mask & MHU_2_1_INTR_CHCOMB_MASK) {
1022+ /* Combined channel IRQ is not present in v2.0 */
1023+ return MHU_V_2_X_ERR_INVALID_ARG;
1024+ }
1025+
1026+ if (dev->frame == MHU_V2_X_RECEIVER_FRAME) {
1027+ /* Only sender frame has these registers */
1028+ return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
1029+ }
1030+ }
1031+
1032+ if(dev->frame == MHU_V2_X_SENDER_FRAME) {
1033+ (SEND_FRAME(p_mhu))->int_clr = mask;
1034+ } else {
1035+ (RECV_FRAME(p_mhu))->int_clr = mask;
1036+ }
1037+
1038+ return MHU_V_2_X_ERR_NONE;
1039+}
1040+
1041+enum mhu_v2_x_error_t mhu_v2_1_get_ch_interrupt_num(
1042+ const struct mhu_v2_x_dev_t *dev, uint32_t *channel)
1043+{
1044+ uint32_t i, j, status;
1045+ union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
1046+
1047+ if ( !(dev->is_initialized) ) {
1048+ return MHU_V_2_X_ERR_NOT_INIT;
1049+ }
1050+
1051+ if (dev->subversion != MHU_MINOR_REV_2_1) {
1052+ /* Feature is only supported in MHU v2.1 */
1053+ return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
1054+ }
1055+
1056+ for(i = 0; i < _MHU_V2_1_MAX_CHCOMB_INT; i++) {
1057+ if(dev->frame == MHU_V2_X_SENDER_FRAME) {
1058+ status = (SEND_FRAME(p_mhu))->ch_comb_int_st[i];
1059+ } else {
1060+ status = (RECV_FRAME(p_mhu))->ch_comb_int_st[i];
1061+ }
1062+
1063+ for(j = 0; j < CH_PER_CH_COMB; j++) {
1064+ if ((status >> CH_PER_CH_COMB - j - 1) & (ENABLE)) {
1065+ *channel = (CH_PER_CH_COMB - j -1 + (i * CH_PER_CH_COMB));
1066+ return MHU_V_2_X_ERR_NONE;
1067+ }
1068+ }
1069+ }
1070+
1071+ return MHU_V_2_X_ERR_GENERAL;
1072+}
1073diff --git a/platform/providers/arm/corstone1000/platform.cmake b/platform/providers/arm/corstone1000/platform.cmake
Patrick Williams975a06f2022-10-21 14:42:47 -05001074new file mode 100644
1075index 000000000000..bb778bb9719b
1076--- /dev/null
Brad Bishopbec4ebc2022-08-03 09:55:16 -04001077+++ b/platform/providers/arm/corstone1000/platform.cmake
Patrick Williams975a06f2022-10-21 14:42:47 -05001078@@ -0,0 +1,10 @@
1079+#-------------------------------------------------------------------------------
1080+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
1081+#
1082+# SPDX-License-Identifier: BSD-3-Clause
1083+#
1084+# Platform definition for the 'fvp_base_revc-2xaem8a' virtual platform.
1085+#-------------------------------------------------------------------------------
1086+
Brad Bishopbec4ebc2022-08-03 09:55:16 -04001087+# include MHU driver
1088+include(${TS_ROOT}/platform/drivers/arm/mhu_driver/component.cmake)
Patrick Williams8dd68482022-10-04 07:57:18 -05001089--
Patrick Williams975a06f2022-10-21 14:42:47 -050010902.38.0
Patrick Williams8dd68482022-10-04 07:57:18 -05001091