1 /*
2 * Copyright (c) 2023 Arm Limited
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "mhu_v3_x.h"
18
19 #include <stddef.h>
20 #include <stdint.h>
21 #include <stdbool.h>
22
23 /**
24 * \brief Postbox control page structure
25 */
26 struct _mhu_v3_x_pbx_ctrl_reg_t {
27 /* Offset: 0x000 (R/ ) Postbox Block Identifier */
28 const volatile uint32_t mhu_blk_id;
29 /* Offset: 0x004 (R/ ) Reserved */
30 const volatile uint8_t reserved_0[0x10 - 0x04];
31 /* Offset: 0x010 (R/ ) Postbox Feature Support 0 */
32 const volatile uint32_t pbx_feat_spt0;
33 /* Offset: 0x014 (R/ ) Postbox Feature Support 1 */
34 const volatile uint32_t pbx_feat_spt1;
35 /* Offset: 0x018 (R/ ) Reserved */
36 const volatile uint8_t reserved_1[0x20 - 0x18];
37 /* Offset: 0x020 (R/ ) Postbox Doorbell Channel Configuration 0 */
38 const volatile uint32_t pbx_dbch_cfg0;
39 /* Offset: 0x024 (R/ ) Reserved */
40 const volatile uint8_t reserved_2[0x30 - 0x24];
41 /* Offset: 0x030 (R/ ) Postbox FIFO Channel Configuration 0 */
42 const volatile uint32_t pbx_ffch_cfg0;
43 /* Offset: 0x034 (R/ ) Reserved */
44 const volatile uint8_t reserved_3[0x40 - 0x34];
45 /* Offset: 0x040 (R/ ) Postbox Fast Channel Configuration 0 */
46 const volatile uint32_t pbx_fch_cfg0;
47 /* Offset: 0x044 (R/ ) Reserved */
48 const volatile uint8_t reserved_4[0x100 - 0x44];
49 /* Offset: 0x100 (R/W) Postbox control */
50 volatile uint32_t pbx_ctrl;
51 /* Offset: 0x164 (R/ ) Reserved */
52 const volatile uint8_t reserved_5[0x400 - 0x104];
53 /*
54 * Offset: 0x400 (R/ ) Postbox Doorbell Channel Interrupt Status n, where
55 * n is 0 - 3.
56 */
57 const volatile uint32_t pbx_dbch_int_st[4];
58 /*
59 * Offset: 0x410 (R/ ) Postbox FIFO Channel <n> Interrupt Status n, where n
60 * is 0 - 1.
61 */
62 const volatile uint32_t pbx_ffch_int_st[2];
63 /* Offset: 0x418 (R/ ) Reserved */
64 const uint8_t reserved_6[0xFC8 - 0x418];
65 /* Offset: 0xFC8 (R/ ) Postbox Implementer Identification Register */
66 const volatile uint32_t iidr;
67 /* Offset: 0xFCC (R/ ) Postbox Architecture Identification Register */
68 const volatile uint32_t aidr;
69 /*
70 * Offset: 0xFD0 (R/ ) Postbox Implementation Defined Identification
71 * Register n, where n is 0 - 11.
72 */
73 const volatile uint32_t impl_def_id[12];
74 };
75
76 /**
77 * \brief Postbox doorbell channel window page structure
78 */
79 struct _mhu_v3_x_pbx_pdbcw_reg_t {
80 /* Offset: 0x000 (R/ ) Postbox Doorbell Channel Window Status */
81 const volatile uint32_t pdbcw_st;
82 /* Offset: 0x004 (R/ ) Reserved */
83 const uint8_t reserved_0[0xC - 0x4];
84 /* Offset: 0x00C ( /W) Postbox Doorbell Channel Window Set */
85 volatile uint32_t pdbcw_set;
86 /* Offset: 0x010 (R/ ) Postbox Doorbell Channel Window Interrupt Status */
87 const volatile uint32_t pdbcw_int_st;
88 /* Offset: 0x014 ( /W) Postbox Doorbell Channel Window Interrupt Clear */
89 volatile uint32_t pdbcw_int_clr;
90 /* Offset: 0x018 (R/W) Postbox Doorbell Channel Window Interrupt Enable */
91 volatile uint32_t pdbcw_int_en;
92 /* Offset: 0x01C (R/W) Postbox Doorbell Channel Window Control */
93 volatile uint32_t pdbcw_ctrl;
94 };
95
96 /**
97 * \brief Postbox structure
98 */
99 struct _mhu_v3_x_pbx {
100 /* Postbox Control */
101 struct _mhu_v3_x_pbx_ctrl_reg_t pbx_ctrl_page;
102 /* Postbox Doorbell Channel Window */
103 struct _mhu_v3_x_pbx_pdbcw_reg_t pdbcw_page;
104 };
105
106 /**
107 * \brief Mailbox control page structure
108 */
109 struct _mhu_v3_x_mbx_ctrl_reg_t {
110 /* Offset: 0x000 (R/ ) Mailbox Block Identifier */
111 const volatile uint32_t mhu_blk_id;
112 /* Offset: 0x004 (R/ ) Reserved */
113 const volatile uint8_t reserved_0[0x10 - 0x04];
114 /* Offset: 0x010 (R/ ) Mailbox Feature Support 0 */
115 const volatile uint32_t mbx_feat_spt0;
116 /* Offset: 0x014 (R/ ) Mailbox Feature Support 1 */
117 const volatile uint32_t mbx_feat_spt1;
118 /* Offset: 0x018 (R/ ) Reserved */
119 const volatile uint8_t reserved_1[0x20 - 0x18];
120 /* Offset: 0x020 (R/ ) Mailbox Doorbell Channel Configuration 0 */
121 const volatile uint32_t mbx_dbch_cfg0;
122 /* Offset: 0x024 (R/ ) Reserved */
123 const volatile uint8_t reserved_2[0x30 - 0x24];
124 /* Offset: 0x030 (R/ ) Mailbox FIFO Channel Configuration 0 */
125 const volatile uint32_t mbx_ffch_cfg0;
126 /* Offset: 0x034 (R/ ) Reserved */
127 const volatile uint8_t reserved_4[0x40 - 0x34];
128 /* Offset: 0x040 (R/ ) Mailbox Fast Channel Configuration 0 */
129 const volatile uint32_t mbx_fch_cfg0;
130 /* Offset: 0x044 (R/ ) Reserved */
131 const volatile uint8_t reserved_5[0x100 - 0x44];
132 /* Offset: 0x100 (R/W) Mailbox control */
133 volatile uint32_t mbx_ctrl;
134 /* Offset: 0x104 (R/ ) Reserved */
135 const volatile uint8_t reserved_6[0x140 - 0x104];
136 /* Offset: 0x140 (R/W) Mailbox Fast Channel control */
137 volatile uint32_t mbx_fch_ctrl;
138 /* Offset: 0x144 (R/W) Mailbox Fast Channel Group Interrupt Enable */
139 volatile uint32_t mbx_fcg_int_en;
140 /* Offset: 0x148 (R/ ) Reserved */
141 const volatile uint8_t reserved_7[0x400 - 0x148];
142 /*
143 * Offset: 0x400 (R/ ) Mailbox Doorbell Channel Interrupt Status n, where
144 * n = 0 - 3.
145 */
146 const volatile uint32_t mbx_dbch_int_st[4];
147 /*
148 * Offset: 0x410 (R/ ) Mailbox FIFO Channel Interrupt Status n, where
149 * n = 0 - 1.
150 */
151 const volatile uint32_t mbx_ffch_int_st[2];
152 /* Offset: 0x418 (R/ ) Reserved */
153 const volatile uint8_t reserved_8[0x470 - 0x418];
154 /* Offset: 0x470 (R/ ) Mailbox Fast Channel Group Interrupt Status */
155 const volatile uint32_t mbx_fcg_int_st;
156 /* Offset: 0x474 (R/ ) Reserved */
157 const volatile uint8_t reserved_9[0x480 - 0x474];
158 /*
159 * Offset: 0x480 (R/ ) Mailbox Fast Channel Group <n> Interrupt Status,
160 * where n = 0 - 31.
161 */
162 const volatile uint32_t mbx_fch_grp_int_st[32];
163 /* Offset: 0x500 (R/ ) Reserved */
164 const volatile uint8_t reserved_10[0xFC8 - 0x500];
165 /* Offset: 0xFC8 (R/ ) Mailbox Implementer Identification Register */
166 const volatile uint32_t iidr;
167 /* Offset: 0xFCC (R/ ) Mailbox Architecture Identification Register */
168 const volatile uint32_t aidr;
169 /*
170 * Offset: 0xFD0 (R/ ) Mailbox Implementation Defined Identification
171 * Register n, where n is 0 - 11.
172 */
173 const volatile uint32_t impl_def_id[12];
174 };
175
176 /**
177 * \brief Mailbox doorbell channel window page structure
178 */
179 struct _mhu_v3_x_mbx_mdbcw_reg_t {
180 /* Offset: 0x000 (R/ ) Mailbox Doorbell Channel Window Status */
181 const volatile uint32_t mdbcw_st;
182 /* Offset: 0x004 (R/ ) Mailbox Doorbell Channel Window Status Masked */
183 const volatile uint32_t mdbcw_st_msk;
184 /* Offset: 0x008 ( /W) Mailbox Doorbell Channel Window Clear */
185 volatile uint32_t mdbcw_clr;
186 /* Offset: 0x00C (R/ ) Reserved */
187 const volatile uint8_t reserved_0[0x10 - 0x0C];
188 /* Offset: 0x010 (R/ ) Mailbox Doorbell Channel Window Mask Status */
189 const volatile uint32_t mdbcw_msk_st;
190 /* Offset: 0x014 ( /W) Mailbox Doorbell Channel Window Mask Set */
191 volatile uint32_t mdbcw_msk_set;
192 /* Offset: 0x018 ( /W) Mailbox Doorbell Channel Window Mask Clear */
193 volatile uint32_t mdbcw_msk_clr;
194 /* Offset: 0x01C (R/W) Mailbox Doorbell Channel Window Control */
195 volatile uint32_t mdbcw_ctrl;
196 };
197
198 /**
199 * \brief Mailbox structure
200 */
201 struct _mhu_v3_x_mbx {
202 /* Mailbox control */
203 struct _mhu_v3_x_mbx_ctrl_reg_t mbx_ctrl_page;
204 /* Mailbox Doorbell Channel Window */
205 struct _mhu_v3_x_mbx_mdbcw_reg_t mdbcw_page;
206 };
207
208 /**
209 * \brief MHUv3 frame type
210 */
211 union _mhu_v3_x_frame_t {
212 /* Postbox Frame */
213 struct _mhu_v3_x_pbx pbx_frame;
214 /* Mailbox Frame */
215 struct _mhu_v3_x_mbx mbx_frame;
216 };
217
218 /**
219 * \brief Enables the doorbell channel to contribute to combined interrupt
220 *
221 * \param[in] dev MHU device struct \ref mhu_v3_x_dev_t
222 * \param[in] channel Channel number
223 *
224 * \return Nothing
225 *
226 * \note For sender channels, transfer acknowledge event interrupt is also
227 * enabled.
228 */
_mhu_v3_x_doorbell_interrupt_enable(const struct mhu_v3_x_dev_t * dev,uint32_t channel)229 static void _mhu_v3_x_doorbell_interrupt_enable(
230 const struct mhu_v3_x_dev_t *dev, uint32_t channel)
231 {
232 union _mhu_v3_x_frame_t *p_mhu;
233
234 p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
235
236 if(dev->frame == MHU_V3_X_PBX_FRAME) {
237 struct _mhu_v3_x_pbx_pdbcw_reg_t *pdbcw_reg;
238 pdbcw_reg = (struct _mhu_v3_x_pbx_pdbcw_reg_t *)
239 &(p_mhu->pbx_frame.pdbcw_page);
240
241 /*
242 * Enable this doorbell channel to generate interrupts for transfer
243 * acknowledge events.
244 */
245 pdbcw_reg[channel].pdbcw_int_en = 0x1;
246
247 /*
248 * Enable this doorbell channel to contribute to the PBX combined
249 * interrupt.
250 */
251 pdbcw_reg[channel].pdbcw_ctrl = 0x1;
252 } else {
253 struct _mhu_v3_x_mbx_mdbcw_reg_t *mdbcw_reg;
254 mdbcw_reg = (struct _mhu_v3_x_mbx_mdbcw_reg_t *)
255 &(p_mhu->mbx_frame.mdbcw_page);
256
257 /*
258 * Enable this doorbell channel to contribute to the MBX combined
259 * interrupt.
260 */
261 mdbcw_reg[channel].mdbcw_ctrl = 0x1;
262 }
263 }
264
265 /**
266 * \brief Disables the doorbell channel from contributing to combined interrupt
267 *
268 * \param[in] dev MHU device struct \ref mhu_v3_x_dev_t
269 * \param[in] channel Channel number
270 *
271 * \return Nothing
272 *
273 * \note For sender channels, transfer acknowledge event interrupt is also
274 * disabled.
275 */
_mhu_v3_x_doorbell_interrupt_disable(const struct mhu_v3_x_dev_t * dev,uint32_t channel)276 static void _mhu_v3_x_doorbell_interrupt_disable(
277 const struct mhu_v3_x_dev_t *dev, uint32_t channel)
278 {
279 union _mhu_v3_x_frame_t *p_mhu;
280
281 p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
282
283 if(dev->frame == MHU_V3_X_PBX_FRAME) {
284 struct _mhu_v3_x_pbx_pdbcw_reg_t *pdbcw_reg;
285 pdbcw_reg = (struct _mhu_v3_x_pbx_pdbcw_reg_t *)
286 &(p_mhu->pbx_frame.pdbcw_page);
287
288 /* Clear channel transfer acknowledge event interrupt */
289 pdbcw_reg[channel].pdbcw_int_clr = 0x1;
290
291 /* Disable channel transfer acknowledge event interrupt */
292 pdbcw_reg[channel].pdbcw_int_en &= ~(0x1);
293
294 /*
295 * Disable this doorbell channel from contributing to the PBX combined
296 * interrupt.
297 */
298 pdbcw_reg[channel].pdbcw_ctrl &= ~(0x1);
299 } else {
300 struct _mhu_v3_x_mbx_mdbcw_reg_t *mdbcw_reg;
301 mdbcw_reg = (struct _mhu_v3_x_mbx_mdbcw_reg_t *)
302 &(p_mhu->mbx_frame.mdbcw_page);
303
304 /*
305 * Disable this doorbell channel from contributing to the MBX combined
306 * interrupt.
307 */
308 mdbcw_reg[channel].mdbcw_ctrl &= ~(0x1);
309 }
310 }
311
312 /**
313 * \brief Clears the doorbell channel transfer acknowledge event interrupt
314 *
315 * \param[in] dev MHU device struct \ref mhu_v3_x_dev_t
316 * \param[in] channel Channel number
317 *
318 * \return Nothing
319 */
_mhu_v3_x_doorbell_interrupt_clear(const struct mhu_v3_x_dev_t * dev,uint32_t channel)320 static void _mhu_v3_x_doorbell_interrupt_clear(
321 const struct mhu_v3_x_dev_t *dev, uint32_t channel)
322 {
323 union _mhu_v3_x_frame_t *p_mhu;
324 struct _mhu_v3_x_pbx_pdbcw_reg_t *pdbcw_reg;
325
326 p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
327 pdbcw_reg = (struct _mhu_v3_x_pbx_pdbcw_reg_t *)&(p_mhu->
328 pbx_frame.pdbcw_page);
329
330 /* Clear channel transfer acknowledge event interrupt */
331 pdbcw_reg[channel].pdbcw_int_clr = 0x1;
332 }
333
mhu_v3_x_driver_init(struct mhu_v3_x_dev_t * dev)334 enum mhu_v3_x_error_t mhu_v3_x_driver_init(struct mhu_v3_x_dev_t *dev)
335 {
336 uint32_t aidr = 0;
337 uint8_t mhu_major_rev;
338 union _mhu_v3_x_frame_t *p_mhu;
339
340 if (dev == NULL) {
341 return MHU_V_3_X_ERR_INVALID_PARAM;
342 }
343
344 /* Return if already initialized */
345 if (dev->is_initialized) {
346 return MHU_V_3_X_ERR_NONE;
347 }
348
349 p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
350
351 /* Read revision from MHU hardware */
352 if (dev->frame == MHU_V3_X_MBX_FRAME) {
353 aidr = p_mhu->mbx_frame.mbx_ctrl_page.aidr;
354 } else {
355 aidr = p_mhu->pbx_frame.pbx_ctrl_page.aidr;
356 }
357
358 /* Read the MHU Architecture Major Revision */
359 mhu_major_rev =
360 ((aidr & MHU_ARCH_MAJOR_REV_MASK) >> MHU_ARCH_MAJOR_REV_OFF);
361
362 /* Return error if the MHU major revision is not 3 */
363 if (mhu_major_rev != MHU_MAJOR_REV_V3) {
364 /* Unsupported MHU version */
365 return MHU_V_3_X_ERR_UNSUPPORTED_VERSION;
366 }
367
368 /* Read the MHU Architecture Minor Revision */
369 dev->subversion =
370 ((aidr & MHU_ARCH_MINOR_REV_MASK) >> MHU_ARCH_MINOR_REV_MASK);
371
372 /* Return error if the MHU minor revision is not 0 */
373 if (dev->subversion != MHU_MINOR_REV_3_0) {
374 /* Unsupported subversion */
375 return MHU_V_3_X_ERR_UNSUPPORTED_VERSION;
376 }
377
378 /* Initialize the Postbox/Mailbox to remain in operational state */
379 if (dev->frame == MHU_V3_X_MBX_FRAME) {
380 p_mhu->mbx_frame.mbx_ctrl_page.mbx_ctrl |= MHU_V3_OP_REQ;
381 } else{
382 p_mhu->pbx_frame.pbx_ctrl_page.pbx_ctrl |= MHU_V3_OP_REQ;
383 }
384
385 dev->is_initialized = true;
386
387 return MHU_V_3_X_ERR_NONE;
388 }
389
mhu_v3_x_get_num_channel_implemented(const struct mhu_v3_x_dev_t * dev,enum mhu_v3_x_channel_type_t ch_type,uint8_t * num_ch)390 enum mhu_v3_x_error_t mhu_v3_x_get_num_channel_implemented(
391 const struct mhu_v3_x_dev_t *dev,
392 enum mhu_v3_x_channel_type_t ch_type, uint8_t *num_ch)
393 {
394 union _mhu_v3_x_frame_t *p_mhu;
395
396 if ((dev == NULL) || (num_ch == NULL)) {
397 return MHU_V_3_X_ERR_INVALID_PARAM;
398 }
399
400 p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
401
402 /* Only doorbell channel is supported */
403 if (ch_type != MHU_V3_X_CHANNEL_TYPE_DBCH) {
404 return MHU_V_3_X_ERR_UNSUPPORTED;
405 }
406
407 /* Read the number of channels implemented in the MHU */
408 if(dev->frame == MHU_V3_X_PBX_FRAME) {
409 *num_ch = (p_mhu->pbx_frame.pbx_ctrl_page.pbx_dbch_cfg0 + 1);
410 } else {
411 *num_ch = (p_mhu->mbx_frame.mbx_ctrl_page.mbx_dbch_cfg0 + 1);
412 }
413
414 return MHU_V_3_X_ERR_NONE;
415 }
416
mhu_v3_x_doorbell_clear(struct mhu_v3_x_dev_t * dev,uint32_t channel,uint32_t mask)417 enum mhu_v3_x_error_t mhu_v3_x_doorbell_clear(struct mhu_v3_x_dev_t *dev,
418 uint32_t channel, uint32_t mask)
419 {
420 union _mhu_v3_x_frame_t *p_mhu;
421 struct _mhu_v3_x_mbx_mdbcw_reg_t *mdbcw_reg;
422 enum mhu_v3_x_error_t status;
423
424 if (dev == NULL) {
425 return MHU_V_3_X_ERR_INVALID_PARAM;
426 }
427
428 /* Check if driver has been initialized */
429 if (!(dev->is_initialized)) {
430 status = mhu_v3_x_driver_init(dev);
431 if (status != MHU_V_3_X_ERR_NONE) {
432 return status;
433 }
434 }
435
436 /* Only MBX can clear the Doorbell channel */
437 if(dev->frame != MHU_V3_X_MBX_FRAME) {
438 return MHU_V_3_X_ERR_INVALID_PARAM;
439 }
440
441 p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
442 mdbcw_reg = (struct _mhu_v3_x_mbx_mdbcw_reg_t *)
443 &(p_mhu->mbx_frame.mdbcw_page);
444
445 /* Clear the bits in the doorbell channel */
446 mdbcw_reg[channel].mdbcw_clr = mask;
447
448 return MHU_V_3_X_ERR_NONE;
449 }
450
mhu_v3_x_doorbell_write(struct mhu_v3_x_dev_t * dev,uint32_t channel,uint32_t value)451 enum mhu_v3_x_error_t mhu_v3_x_doorbell_write(struct mhu_v3_x_dev_t *dev,
452 uint32_t channel, uint32_t value)
453 {
454 union _mhu_v3_x_frame_t *p_mhu;
455 struct _mhu_v3_x_pbx_pdbcw_reg_t *pdbcw_reg;
456 enum mhu_v3_x_error_t status;
457
458 if (dev == NULL) {
459 return MHU_V_3_X_ERR_INVALID_PARAM;
460 }
461
462 /* Check if driver has been initialized */
463 if (!(dev->is_initialized)) {
464 status = mhu_v3_x_driver_init(dev);
465 if (status != MHU_V_3_X_ERR_NONE) {
466 return status;
467 }
468 }
469
470 /* Only PBX can set the Doorbell channel value */
471 if (dev->frame != MHU_V3_X_PBX_FRAME) {
472 return MHU_V_3_X_ERR_INVALID_PARAM;
473 }
474
475 p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
476
477 pdbcw_reg = (struct _mhu_v3_x_pbx_pdbcw_reg_t *)
478 &(p_mhu->pbx_frame.pdbcw_page);
479
480 /* Write the value to the doorbell channel */
481 pdbcw_reg[channel].pdbcw_set = value;
482
483 return MHU_V_3_X_ERR_NONE;
484 }
485
mhu_v3_x_doorbell_read(struct mhu_v3_x_dev_t * dev,uint32_t channel,uint32_t * value)486 enum mhu_v3_x_error_t mhu_v3_x_doorbell_read(struct mhu_v3_x_dev_t *dev,
487 uint32_t channel, uint32_t *value)
488 {
489 union _mhu_v3_x_frame_t *p_mhu;
490 enum mhu_v3_x_error_t status;
491
492 if ((dev == NULL) || (value == NULL)) {
493 return MHU_V_3_X_ERR_INVALID_PARAM;
494 }
495
496 /* Check if driver has been initialized */
497 if (!(dev->is_initialized)) {
498 status = mhu_v3_x_driver_init(dev);
499 if (status != MHU_V_3_X_ERR_NONE) {
500 return status;
501 }
502 }
503
504 p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
505
506 if(dev->frame == MHU_V3_X_MBX_FRAME) {
507 struct _mhu_v3_x_mbx_mdbcw_reg_t *mdbcw_reg;
508 mdbcw_reg = (struct _mhu_v3_x_mbx_mdbcw_reg_t *)
509 &(p_mhu->mbx_frame.mdbcw_page);
510
511 /* Read the value from Mailbox Doorbell status register */
512 *value = mdbcw_reg[channel].mdbcw_st;
513 } else {
514 struct _mhu_v3_x_pbx_pdbcw_reg_t *pdbcw_reg;
515 pdbcw_reg = (struct _mhu_v3_x_pbx_pdbcw_reg_t *)
516 &(p_mhu->pbx_frame.pdbcw_page);
517
518 /* Read the value from Postbox Doorbell status register */
519 *value = pdbcw_reg[channel].pdbcw_st;
520 }
521
522 return MHU_V_3_X_ERR_NONE;
523 }
524
mhu_v3_x_doorbell_mask_set(struct mhu_v3_x_dev_t * dev,uint32_t channel,uint32_t mask)525 enum mhu_v3_x_error_t mhu_v3_x_doorbell_mask_set(
526 struct mhu_v3_x_dev_t *dev, uint32_t channel, uint32_t mask)
527 {
528 union _mhu_v3_x_frame_t *p_mhu;
529 struct _mhu_v3_x_mbx_mdbcw_reg_t *mdbcw_reg;
530 enum mhu_v3_x_error_t status;
531
532 if (dev == NULL) {
533 return MHU_V_3_X_ERR_INVALID_PARAM;
534 }
535
536 /* Check if driver has been initialized */
537 if (!(dev->is_initialized) ) {
538 status = mhu_v3_x_driver_init(dev);
539 if (status != MHU_V_3_X_ERR_NONE) {
540 return status;
541 }
542 }
543
544 /* Doorbell channel mask not applicable for PBX */
545 if(dev->frame != MHU_V3_X_MBX_FRAME) {
546 return MHU_V_3_X_ERR_INVALID_PARAM;
547 }
548
549 p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
550
551 mdbcw_reg = (struct _mhu_v3_x_mbx_mdbcw_reg_t *)
552 &(p_mhu->mbx_frame.mdbcw_page);
553
554 /* Set the Doorbell channel mask */
555 mdbcw_reg[channel].mdbcw_msk_set = mask;
556
557 return MHU_V_3_X_ERR_NONE;
558 }
559
mhu_v3_x_doorbell_mask_clear(struct mhu_v3_x_dev_t * dev,uint32_t channel,uint32_t mask)560 enum mhu_v3_x_error_t mhu_v3_x_doorbell_mask_clear(
561 struct mhu_v3_x_dev_t *dev, uint32_t channel, uint32_t mask)
562 {
563 union _mhu_v3_x_frame_t *p_mhu;
564 struct _mhu_v3_x_mbx_mdbcw_reg_t *mdbcw_reg;
565 enum mhu_v3_x_error_t status;
566
567 if (dev == NULL) {
568 return MHU_V_3_X_ERR_INVALID_PARAM;
569 }
570
571 /* Check if driver has been initialized */
572 if (!(dev->is_initialized)) {
573 status = mhu_v3_x_driver_init(dev);
574 if (status != MHU_V_3_X_ERR_NONE) {
575 return status;
576 }
577 }
578
579 /* Doorbell channel mask not applicable for PBX */
580 if(dev->frame != MHU_V3_X_MBX_FRAME) {
581 return MHU_V_3_X_ERR_INVALID_PARAM;
582 }
583
584 p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
585
586 mdbcw_reg = (struct _mhu_v3_x_mbx_mdbcw_reg_t *)
587 &(p_mhu->mbx_frame.mdbcw_page);
588
589 /* Clear the Doorbell channel mask */
590 mdbcw_reg[channel].mdbcw_msk_clr = mask;
591
592 return MHU_V_3_X_ERR_NONE;
593 }
594
mhu_v3_x_doorbell_mask_get(struct mhu_v3_x_dev_t * dev,uint32_t channel,uint32_t * mask_status)595 enum mhu_v3_x_error_t mhu_v3_x_doorbell_mask_get(
596 struct mhu_v3_x_dev_t *dev, uint32_t channel, uint32_t *mask_status)
597 {
598 union _mhu_v3_x_frame_t *p_mhu;
599 struct _mhu_v3_x_mbx_mdbcw_reg_t *mdbcw_reg;
600 enum mhu_v3_x_error_t status;
601
602 if ((dev == NULL) || (mask_status == NULL)) {
603 return MHU_V_3_X_ERR_INVALID_PARAM;
604 }
605
606 /* Check if driver has been initialized */
607 if (!(dev->is_initialized)) {
608 status = mhu_v3_x_driver_init(dev);
609 if (status != MHU_V_3_X_ERR_NONE) {
610 return status;
611 }
612 }
613
614 /* Doorbell channel mask not applicable for PBX */
615 if(dev->frame != MHU_V3_X_MBX_FRAME) {
616 return MHU_V_3_X_ERR_INVALID_PARAM;
617 }
618
619 p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
620
621 mdbcw_reg = (struct _mhu_v3_x_mbx_mdbcw_reg_t *)
622 &(p_mhu->mbx_frame.mdbcw_page);
623
624 /* Save the Doorbell channel mask status */
625 *mask_status = mdbcw_reg[channel].mdbcw_msk_st;
626
627 return MHU_V_3_X_ERR_NONE;
628 }
629
mhu_v3_x_channel_interrupt_enable(struct mhu_v3_x_dev_t * dev,uint32_t channel,enum mhu_v3_x_channel_type_t ch_type)630 enum mhu_v3_x_error_t mhu_v3_x_channel_interrupt_enable(
631 struct mhu_v3_x_dev_t *dev, uint32_t channel,
632 enum mhu_v3_x_channel_type_t ch_type)
633 {
634 enum mhu_v3_x_error_t status;
635
636 if (dev == NULL) {
637 return MHU_V_3_X_ERR_INVALID_PARAM;
638 }
639
640 /* Check if driver has been initialized */
641 if (!(dev->is_initialized)) {
642 status = mhu_v3_x_driver_init(dev);
643 if (status != MHU_V_3_X_ERR_NONE) {
644 return status;
645 }
646 }
647
648 /* Only doorbell channel is supported */
649 if (ch_type != MHU_V3_X_CHANNEL_TYPE_DBCH) {
650 return MHU_V_3_X_ERR_UNSUPPORTED;
651 }
652
653 /* Enable the doorbell channel interrupt */
654 _mhu_v3_x_doorbell_interrupt_enable(dev, channel);
655
656 return MHU_V_3_X_ERR_NONE;
657 }
658
mhu_v3_x_channel_interrupt_disable(struct mhu_v3_x_dev_t * dev,uint32_t channel,enum mhu_v3_x_channel_type_t ch_type)659 enum mhu_v3_x_error_t mhu_v3_x_channel_interrupt_disable(
660 struct mhu_v3_x_dev_t *dev, uint32_t channel,
661 enum mhu_v3_x_channel_type_t ch_type)
662 {
663 enum mhu_v3_x_error_t status;
664
665 /* Check if driver has been initialized */
666 if (!(dev->is_initialized)) {
667 status = mhu_v3_x_driver_init(dev);
668 if (status != MHU_V_3_X_ERR_NONE) {
669 return status;
670 }
671 }
672
673 /* Only doorbell channel is supported */
674 if (ch_type != MHU_V3_X_CHANNEL_TYPE_DBCH) {
675 return MHU_V_3_X_ERR_UNSUPPORTED;
676 }
677
678 /* Disable the doorbell channel interrupt */
679 _mhu_v3_x_doorbell_interrupt_disable(dev, channel);
680
681 return MHU_V_3_X_ERR_NONE;
682 }
683
mhu_v3_x_channel_interrupt_clear(struct mhu_v3_x_dev_t * dev,uint32_t channel,enum mhu_v3_x_channel_type_t ch_type)684 enum mhu_v3_x_error_t mhu_v3_x_channel_interrupt_clear(
685 struct mhu_v3_x_dev_t *dev, uint32_t channel,
686 enum mhu_v3_x_channel_type_t ch_type)
687 {
688 enum mhu_v3_x_error_t status;
689
690 /* Check if driver has been initialized */
691 if (!(dev->is_initialized)) {
692 status = mhu_v3_x_driver_init(dev);
693 if (status != MHU_V_3_X_ERR_NONE) {
694 return status;
695 }
696 }
697
698 /* Only doorbell channel is supported */
699 if (ch_type != MHU_V3_X_CHANNEL_TYPE_DBCH) {
700 return MHU_V_3_X_ERR_UNSUPPORTED;
701 }
702
703 /*
704 * Only postbox doorbell channel transfer acknowledge interrupt can be
705 * cleared manually.
706 */
707 if(dev->frame != MHU_V3_X_PBX_FRAME) {
708 return MHU_V_3_X_ERR_INVALID_PARAM;
709 }
710
711 /* Clear the postbox doorbell channel transfer acknowledge event */
712 _mhu_v3_x_doorbell_interrupt_clear(dev, channel);
713
714 return MHU_V_3_X_ERR_NONE;
715 }
716