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