xref: /rk3399_ARM-atf/drivers/arm/mhu/mhu_v3_x.c (revision 9fad664ef2f934890690465db15a782045c274ef)
1bc174764SAziz IDOMAR /*
2bc174764SAziz IDOMAR  * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
3bc174764SAziz IDOMAR  *
4bc174764SAziz IDOMAR  * SPDX-License-Identifier: BSD-3-Clause
5bc174764SAziz IDOMAR  */
6bc174764SAziz IDOMAR 
7bc174764SAziz IDOMAR #include <assert.h>
8bc174764SAziz IDOMAR #include <stdbool.h>
9bc174764SAziz IDOMAR #include <stdint.h>
10bc174764SAziz IDOMAR 
11bc174764SAziz IDOMAR #include "mhu_v3_x.h"
12bc174764SAziz IDOMAR 
13bc174764SAziz IDOMAR #include "mhu_v3_x_private.h"
14bc174764SAziz IDOMAR 
15bc174764SAziz IDOMAR /*
16bc174764SAziz IDOMAR  * Get the device base from the device struct. Return an error if the dev is
17bc174764SAziz IDOMAR  * invalid.
18bc174764SAziz IDOMAR  */
19bc174764SAziz IDOMAR static enum mhu_v3_x_error_t get_dev_base(const struct mhu_v3_x_dev_t *dev,
20bc174764SAziz IDOMAR 	 union _mhu_v3_x_frame_t **base)
21bc174764SAziz IDOMAR {
22bc174764SAziz IDOMAR 	if (dev == NULL) {
23bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_INVALID_PARAM;
24bc174764SAziz IDOMAR 	}
25bc174764SAziz IDOMAR 
26bc174764SAziz IDOMAR 	/* Ensure driver has been initialized */
27bc174764SAziz IDOMAR 	if (dev->is_initialized == false) {
28bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_NOT_INIT;
29bc174764SAziz IDOMAR 	}
30bc174764SAziz IDOMAR 
31bc174764SAziz IDOMAR 	*base = (union _mhu_v3_x_frame_t *)dev->base;
32bc174764SAziz IDOMAR 
33bc174764SAziz IDOMAR 	return MHU_V_3_X_ERR_NONE;
34bc174764SAziz IDOMAR }
35bc174764SAziz IDOMAR 
36bc174764SAziz IDOMAR enum mhu_v3_x_error_t mhu_v3_x_driver_init(struct mhu_v3_x_dev_t *dev)
37bc174764SAziz IDOMAR {
38bc174764SAziz IDOMAR 	uint32_t aidr = 0;
39bc174764SAziz IDOMAR 	uint8_t mhu_major_rev;
40bc174764SAziz IDOMAR 	union _mhu_v3_x_frame_t *p_mhu;
41bc174764SAziz IDOMAR 
42bc174764SAziz IDOMAR 	if (dev == NULL) {
43bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_INVALID_PARAM;
44bc174764SAziz IDOMAR 	}
45bc174764SAziz IDOMAR 
46bc174764SAziz IDOMAR 	/* Return if already initialized */
47bc174764SAziz IDOMAR 	if (dev->is_initialized == true) {
48bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_NONE;
49bc174764SAziz IDOMAR 	}
50bc174764SAziz IDOMAR 
51bc174764SAziz IDOMAR 	p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
52bc174764SAziz IDOMAR 
53bc174764SAziz IDOMAR 	/* Read revision from MHU hardware */
54bc174764SAziz IDOMAR 	if (dev->frame == MHU_V3_X_PBX_FRAME) {
55bc174764SAziz IDOMAR 		aidr = p_mhu->pbx_frame.pbx_ctrl_page.pbx_aidr;
56bc174764SAziz IDOMAR 	} else if (dev->frame == MHU_V3_X_MBX_FRAME) {
57bc174764SAziz IDOMAR 		aidr = p_mhu->mbx_frame.mbx_ctrl_page.mbx_aidr;
58bc174764SAziz IDOMAR 	} else {
59bc174764SAziz IDOMAR 		/* Only PBX and MBX frames are supported. */
60bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_UNSUPPORTED;
61bc174764SAziz IDOMAR 	}
62bc174764SAziz IDOMAR 
63bc174764SAziz IDOMAR 	/* Read the MHU Architecture Major Revision */
64bc174764SAziz IDOMAR 	mhu_major_rev =
65bc174764SAziz IDOMAR 		((aidr & MHU_ARCH_MAJOR_REV_MASK) >> MHU_ARCH_MAJOR_REV_OFF);
66bc174764SAziz IDOMAR 
67bc174764SAziz IDOMAR 	/* Return error if the MHU major revision is not 3 */
68bc174764SAziz IDOMAR 	if (mhu_major_rev != MHU_MAJOR_REV_V3) {
69bc174764SAziz IDOMAR 		/* Unsupported MHU version */
70bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_UNSUPPORTED_VERSION;
71bc174764SAziz IDOMAR 	}
72bc174764SAziz IDOMAR 
73bc174764SAziz IDOMAR 	/* Read the MHU Architecture Minor Revision */
74bc174764SAziz IDOMAR 	dev->subversion =
75*9fad664eSOlivier Deprez 		((aidr & MHU_ARCH_MINOR_REV_MASK) >> MHU_ARCH_MINOR_REV_OFF);
76bc174764SAziz IDOMAR 
77bc174764SAziz IDOMAR 	/* Return error if the MHU minor revision is not 0 */
78bc174764SAziz IDOMAR 	if (dev->subversion != MHU_MINOR_REV_3_0) {
79bc174764SAziz IDOMAR 		/* Unsupported subversion */
80bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_UNSUPPORTED_VERSION;
81bc174764SAziz IDOMAR 	}
82bc174764SAziz IDOMAR 
83bc174764SAziz IDOMAR 	/* Initialize the Postbox/Mailbox to remain in operational state */
84bc174764SAziz IDOMAR 	if (dev->frame == MHU_V3_X_PBX_FRAME) {
85bc174764SAziz IDOMAR 		p_mhu->pbx_frame.pbx_ctrl_page.pbx_ctrl |= MHU_V3_OP_REQ;
86bc174764SAziz IDOMAR 	} else if (dev->frame == MHU_V3_X_MBX_FRAME) {
87bc174764SAziz IDOMAR 		p_mhu->mbx_frame.mbx_ctrl_page.mbx_ctrl |= MHU_V3_OP_REQ;
88bc174764SAziz IDOMAR 	} else {
89bc174764SAziz IDOMAR 		/* Only PBX and MBX frames are supported. */
90bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_UNSUPPORTED;
91bc174764SAziz IDOMAR 	}
92bc174764SAziz IDOMAR 
93bc174764SAziz IDOMAR 	dev->is_initialized = true;
94bc174764SAziz IDOMAR 
95bc174764SAziz IDOMAR 	return MHU_V_3_X_ERR_NONE;
96bc174764SAziz IDOMAR }
97bc174764SAziz IDOMAR 
98bc174764SAziz IDOMAR enum mhu_v3_x_error_t mhu_v3_x_get_num_channel_implemented(
99bc174764SAziz IDOMAR 	 const struct mhu_v3_x_dev_t *dev,
100bc174764SAziz IDOMAR 	 enum mhu_v3_x_channel_type_t ch_type, uint8_t *num_ch)
101bc174764SAziz IDOMAR {
102bc174764SAziz IDOMAR 	enum mhu_v3_x_error_t status;
103bc174764SAziz IDOMAR 	union _mhu_v3_x_frame_t *p_mhu;
104bc174764SAziz IDOMAR 
105bc174764SAziz IDOMAR 	if (num_ch == NULL) {
106bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_INVALID_PARAM;
107bc174764SAziz IDOMAR 	}
108bc174764SAziz IDOMAR 
109bc174764SAziz IDOMAR 	/* Get dev->base if it is valid or return an error if dev is not */
110bc174764SAziz IDOMAR 	status = get_dev_base(dev, &p_mhu);
111bc174764SAziz IDOMAR 	if (status != MHU_V_3_X_ERR_NONE) {
112bc174764SAziz IDOMAR 		return status;
113bc174764SAziz IDOMAR 	}
114bc174764SAziz IDOMAR 
115bc174764SAziz IDOMAR 	/* Only doorbell channel is supported */
116bc174764SAziz IDOMAR 	if (ch_type != MHU_V3_X_CHANNEL_TYPE_DBCH) {
117bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_UNSUPPORTED;
118bc174764SAziz IDOMAR 	}
119bc174764SAziz IDOMAR 
120bc174764SAziz IDOMAR 	/* Read the number of channels implemented in the MHU */
121bc174764SAziz IDOMAR 	if (dev->frame == MHU_V3_X_PBX_FRAME) {
122bc174764SAziz IDOMAR 		*num_ch = (p_mhu->pbx_frame.pbx_ctrl_page.pbx_dbch_cfg0 + 1);
123bc174764SAziz IDOMAR 	} else if (dev->frame == MHU_V3_X_MBX_FRAME) {
124bc174764SAziz IDOMAR 		*num_ch = (p_mhu->mbx_frame.mbx_ctrl_page.mbx_dbch_cfg0 + 1);
125bc174764SAziz IDOMAR 	} else {
126bc174764SAziz IDOMAR 		/* Only PBX and MBX frames are supported. */
127bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_UNSUPPORTED;
128bc174764SAziz IDOMAR 	}
129bc174764SAziz IDOMAR 
130bc174764SAziz IDOMAR 	return MHU_V_3_X_ERR_NONE;
131bc174764SAziz IDOMAR }
132bc174764SAziz IDOMAR 
133bc174764SAziz IDOMAR enum mhu_v3_x_error_t mhu_v3_x_doorbell_clear(const struct mhu_v3_x_dev_t *dev,
134bc174764SAziz IDOMAR 	 const uint32_t channel, uint32_t flags)
135bc174764SAziz IDOMAR {
136bc174764SAziz IDOMAR 	union _mhu_v3_x_frame_t *p_mhu;
137bc174764SAziz IDOMAR 	struct _mhu_v3_x_mdbcw_reg_t *mdbcw_reg;
138bc174764SAziz IDOMAR 	enum mhu_v3_x_error_t status;
139bc174764SAziz IDOMAR 
140bc174764SAziz IDOMAR 	/* Get dev->base if it is valid or return an error if dev is not */
141bc174764SAziz IDOMAR 	status = get_dev_base(dev, &p_mhu);
142bc174764SAziz IDOMAR 	if (status != MHU_V_3_X_ERR_NONE) {
143bc174764SAziz IDOMAR 		return status;
144bc174764SAziz IDOMAR 	}
145bc174764SAziz IDOMAR 
146bc174764SAziz IDOMAR 	/* Only MBX can clear the Doorbell channel */
147bc174764SAziz IDOMAR 	if (dev->frame != MHU_V3_X_MBX_FRAME) {
148bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_INVALID_PARAM;
149bc174764SAziz IDOMAR 	}
150bc174764SAziz IDOMAR 
151bc174764SAziz IDOMAR 	p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
152bc174764SAziz IDOMAR 	mdbcw_reg = (struct _mhu_v3_x_mdbcw_reg_t *)
153bc174764SAziz IDOMAR 		&(p_mhu->mbx_frame.mdbcw_page);
154bc174764SAziz IDOMAR 
155bc174764SAziz IDOMAR 	/* Clear the bits in the doorbell channel */
156bc174764SAziz IDOMAR 	mdbcw_reg[channel].mdbcw_clr |= flags;
157bc174764SAziz IDOMAR 
158bc174764SAziz IDOMAR 	return MHU_V_3_X_ERR_NONE;
159bc174764SAziz IDOMAR }
160bc174764SAziz IDOMAR 
161bc174764SAziz IDOMAR enum mhu_v3_x_error_t mhu_v3_x_doorbell_write(const struct mhu_v3_x_dev_t *dev,
162bc174764SAziz IDOMAR 	 const uint32_t channel, uint32_t flags)
163bc174764SAziz IDOMAR {
164bc174764SAziz IDOMAR 	union _mhu_v3_x_frame_t *p_mhu;
165bc174764SAziz IDOMAR 	struct _mhu_v3_x_pdbcw_reg_t *pdbcw_reg;
166bc174764SAziz IDOMAR 	enum mhu_v3_x_error_t status;
167bc174764SAziz IDOMAR 
168bc174764SAziz IDOMAR 	/* Get dev->base if it is valid or return an error if dev is not */
169bc174764SAziz IDOMAR 	status = get_dev_base(dev, &p_mhu);
170bc174764SAziz IDOMAR 	if (status != MHU_V_3_X_ERR_NONE) {
171bc174764SAziz IDOMAR 		return status;
172bc174764SAziz IDOMAR 	}
173bc174764SAziz IDOMAR 
174bc174764SAziz IDOMAR 	/* Only PBX can set the Doorbell channel value */
175bc174764SAziz IDOMAR 	if (dev->frame != MHU_V3_X_PBX_FRAME) {
176bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_INVALID_PARAM;
177bc174764SAziz IDOMAR 	}
178bc174764SAziz IDOMAR 
179bc174764SAziz IDOMAR 	p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
180bc174764SAziz IDOMAR 
181bc174764SAziz IDOMAR 	pdbcw_reg = (struct _mhu_v3_x_pdbcw_reg_t *)
182bc174764SAziz IDOMAR 		&(p_mhu->pbx_frame.pdbcw_page);
183bc174764SAziz IDOMAR 
184bc174764SAziz IDOMAR 	/* Write the value to the doorbell channel */
185bc174764SAziz IDOMAR 	pdbcw_reg[channel].pdbcw_set |= flags;
186bc174764SAziz IDOMAR 
187bc174764SAziz IDOMAR 	return MHU_V_3_X_ERR_NONE;
188bc174764SAziz IDOMAR }
189bc174764SAziz IDOMAR 
190bc174764SAziz IDOMAR enum mhu_v3_x_error_t mhu_v3_x_doorbell_read(const struct mhu_v3_x_dev_t *dev,
191bc174764SAziz IDOMAR 	 const uint32_t channel, uint32_t *flags)
192bc174764SAziz IDOMAR {
193bc174764SAziz IDOMAR 	union _mhu_v3_x_frame_t *p_mhu;
194bc174764SAziz IDOMAR 	enum mhu_v3_x_error_t status;
195bc174764SAziz IDOMAR 	struct _mhu_v3_x_mdbcw_reg_t *mdbcw_reg;
196bc174764SAziz IDOMAR 	struct _mhu_v3_x_pdbcw_reg_t *pdbcw_reg;
197bc174764SAziz IDOMAR 
198bc174764SAziz IDOMAR 	if (flags == NULL) {
199bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_INVALID_PARAM;
200bc174764SAziz IDOMAR 	}
201bc174764SAziz IDOMAR 
202bc174764SAziz IDOMAR 	/* Get dev->base if it is valid or return an error if dev is not */
203bc174764SAziz IDOMAR 	status = get_dev_base(dev, &p_mhu);
204bc174764SAziz IDOMAR 	if (status != MHU_V_3_X_ERR_NONE) {
205bc174764SAziz IDOMAR 		return status;
206bc174764SAziz IDOMAR 	}
207bc174764SAziz IDOMAR 
208bc174764SAziz IDOMAR 	p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
209bc174764SAziz IDOMAR 
210bc174764SAziz IDOMAR 	if (dev->frame == MHU_V3_X_PBX_FRAME) {
211bc174764SAziz IDOMAR 		pdbcw_reg = (struct _mhu_v3_x_pdbcw_reg_t *)
212bc174764SAziz IDOMAR 			&(p_mhu->pbx_frame.pdbcw_page);
213bc174764SAziz IDOMAR 
214bc174764SAziz IDOMAR 		/* Read the value from Postbox Doorbell status register */
215bc174764SAziz IDOMAR 		*flags = pdbcw_reg[channel].pdbcw_st;
216bc174764SAziz IDOMAR 	} else if (dev->frame == MHU_V3_X_MBX_FRAME) {
217bc174764SAziz IDOMAR 		mdbcw_reg = (struct _mhu_v3_x_mdbcw_reg_t *)
218bc174764SAziz IDOMAR 			&(p_mhu->mbx_frame.mdbcw_page);
219bc174764SAziz IDOMAR 
220bc174764SAziz IDOMAR 		/* Read the value from Mailbox Doorbell status register */
221bc174764SAziz IDOMAR 		*flags = mdbcw_reg[channel].mdbcw_st;
222bc174764SAziz IDOMAR 	} else {
223bc174764SAziz IDOMAR 		/* Only PBX and MBX frames are supported. */
224bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_UNSUPPORTED;
225bc174764SAziz IDOMAR 	}
226bc174764SAziz IDOMAR 
227bc174764SAziz IDOMAR 	return MHU_V_3_X_ERR_NONE;
228bc174764SAziz IDOMAR }
229bc174764SAziz IDOMAR 
230bc174764SAziz IDOMAR enum mhu_v3_x_error_t mhu_v3_x_doorbell_mask_set(
231bc174764SAziz IDOMAR 	 const struct mhu_v3_x_dev_t *dev, const uint32_t channel,
232bc174764SAziz IDOMAR 	 uint32_t flags)
233bc174764SAziz IDOMAR {
234bc174764SAziz IDOMAR 	union _mhu_v3_x_frame_t *p_mhu;
235bc174764SAziz IDOMAR 	struct _mhu_v3_x_mdbcw_reg_t *mdbcw_reg;
236bc174764SAziz IDOMAR 	enum mhu_v3_x_error_t status;
237bc174764SAziz IDOMAR 
238bc174764SAziz IDOMAR 	/* Get dev->base if it is valid or return an error if dev is not */
239bc174764SAziz IDOMAR 	status = get_dev_base(dev, &p_mhu);
240bc174764SAziz IDOMAR 	if (status != MHU_V_3_X_ERR_NONE) {
241bc174764SAziz IDOMAR 		return status;
242bc174764SAziz IDOMAR 	}
243bc174764SAziz IDOMAR 
244bc174764SAziz IDOMAR 	/* Doorbell channel mask is not applicable for PBX */
245bc174764SAziz IDOMAR 	if (dev->frame != MHU_V3_X_MBX_FRAME) {
246bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_INVALID_PARAM;
247bc174764SAziz IDOMAR 	}
248bc174764SAziz IDOMAR 
249bc174764SAziz IDOMAR 	p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
250bc174764SAziz IDOMAR 
251bc174764SAziz IDOMAR 	mdbcw_reg = (struct _mhu_v3_x_mdbcw_reg_t *)
252bc174764SAziz IDOMAR 		&(p_mhu->mbx_frame.mdbcw_page);
253bc174764SAziz IDOMAR 
254bc174764SAziz IDOMAR 	/* Set the Doorbell channel mask */
255bc174764SAziz IDOMAR 	mdbcw_reg[channel].mdbcw_msk_set |= flags;
256bc174764SAziz IDOMAR 
257bc174764SAziz IDOMAR 	return MHU_V_3_X_ERR_NONE;
258bc174764SAziz IDOMAR }
259bc174764SAziz IDOMAR 
260bc174764SAziz IDOMAR enum mhu_v3_x_error_t mhu_v3_x_doorbell_mask_clear(
261bc174764SAziz IDOMAR 	 const struct mhu_v3_x_dev_t *dev, const uint32_t channel,
262bc174764SAziz IDOMAR 	 uint32_t flags)
263bc174764SAziz IDOMAR {
264bc174764SAziz IDOMAR 	union _mhu_v3_x_frame_t *p_mhu;
265bc174764SAziz IDOMAR 	struct _mhu_v3_x_mdbcw_reg_t *mdbcw_reg;
266bc174764SAziz IDOMAR 	enum mhu_v3_x_error_t status;
267bc174764SAziz IDOMAR 
268bc174764SAziz IDOMAR 	/* Get dev->base if it is valid or return an error if dev is not */
269bc174764SAziz IDOMAR 	status = get_dev_base(dev, &p_mhu);
270bc174764SAziz IDOMAR 	if (status != MHU_V_3_X_ERR_NONE) {
271bc174764SAziz IDOMAR 		return status;
272bc174764SAziz IDOMAR 	}
273bc174764SAziz IDOMAR 
274bc174764SAziz IDOMAR 	/* Doorbell channel mask is not applicable for PBX */
275bc174764SAziz IDOMAR 	if (dev->frame != MHU_V3_X_MBX_FRAME) {
276bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_INVALID_PARAM;
277bc174764SAziz IDOMAR 	}
278bc174764SAziz IDOMAR 
279bc174764SAziz IDOMAR 	p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
280bc174764SAziz IDOMAR 
281bc174764SAziz IDOMAR 	mdbcw_reg = (struct _mhu_v3_x_mdbcw_reg_t *)
282bc174764SAziz IDOMAR 		&(p_mhu->mbx_frame.mdbcw_page);
283bc174764SAziz IDOMAR 
284bc174764SAziz IDOMAR 	/* Clear the Doorbell channel mask */
285bc174764SAziz IDOMAR 	mdbcw_reg[channel].mdbcw_msk_clr = flags;
286bc174764SAziz IDOMAR 
287bc174764SAziz IDOMAR 	return MHU_V_3_X_ERR_NONE;
288bc174764SAziz IDOMAR }
289bc174764SAziz IDOMAR 
290bc174764SAziz IDOMAR enum mhu_v3_x_error_t mhu_v3_x_doorbell_mask_get(
291bc174764SAziz IDOMAR 	 const struct mhu_v3_x_dev_t *dev, const uint32_t channel,
292bc174764SAziz IDOMAR 	 uint32_t *flags)
293bc174764SAziz IDOMAR {
294bc174764SAziz IDOMAR 	union _mhu_v3_x_frame_t *p_mhu;
295bc174764SAziz IDOMAR 	struct _mhu_v3_x_mdbcw_reg_t *mdbcw_reg;
296bc174764SAziz IDOMAR 	enum mhu_v3_x_error_t status;
297bc174764SAziz IDOMAR 
298bc174764SAziz IDOMAR 	if (flags == NULL) {
299bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_INVALID_PARAM;
300bc174764SAziz IDOMAR 	}
301bc174764SAziz IDOMAR 
302bc174764SAziz IDOMAR 	/* Get dev->base if it is valid or return an error if dev is not */
303bc174764SAziz IDOMAR 	status = get_dev_base(dev, &p_mhu);
304bc174764SAziz IDOMAR 	if (status != MHU_V_3_X_ERR_NONE) {
305bc174764SAziz IDOMAR 		return status;
306bc174764SAziz IDOMAR 	}
307bc174764SAziz IDOMAR 
308bc174764SAziz IDOMAR 	/* Doorbell channel mask is not applicable for PBX */
309bc174764SAziz IDOMAR 	if (dev->frame != MHU_V3_X_MBX_FRAME) {
310bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_INVALID_PARAM;
311bc174764SAziz IDOMAR 	}
312bc174764SAziz IDOMAR 
313bc174764SAziz IDOMAR 	p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
314bc174764SAziz IDOMAR 
315bc174764SAziz IDOMAR 	mdbcw_reg = (struct _mhu_v3_x_mdbcw_reg_t *)
316bc174764SAziz IDOMAR 		&(p_mhu->mbx_frame.mdbcw_page);
317bc174764SAziz IDOMAR 
318bc174764SAziz IDOMAR 	/* Save the Doorbell channel mask status */
319bc174764SAziz IDOMAR 	*flags = mdbcw_reg[channel].mdbcw_msk_st;
320bc174764SAziz IDOMAR 
321bc174764SAziz IDOMAR 	return MHU_V_3_X_ERR_NONE;
322bc174764SAziz IDOMAR }
323bc174764SAziz IDOMAR 
324bc174764SAziz IDOMAR enum mhu_v3_x_error_t mhu_v3_x_channel_interrupt_enable(
325bc174764SAziz IDOMAR 	 const struct mhu_v3_x_dev_t *dev, const uint32_t channel,
326bc174764SAziz IDOMAR 	 enum mhu_v3_x_channel_type_t ch_type)
327bc174764SAziz IDOMAR {
328bc174764SAziz IDOMAR 	enum mhu_v3_x_error_t status;
329bc174764SAziz IDOMAR 
330bc174764SAziz IDOMAR 	union _mhu_v3_x_frame_t *p_mhu;
331bc174764SAziz IDOMAR 	struct _mhu_v3_x_pdbcw_reg_t *pdbcw_reg;
332bc174764SAziz IDOMAR 	struct _mhu_v3_x_mdbcw_reg_t *mdbcw_reg;
333bc174764SAziz IDOMAR 
334bc174764SAziz IDOMAR 	/* Get dev->base if it is valid or return an error if dev is not */
335bc174764SAziz IDOMAR 	status = get_dev_base(dev, &p_mhu);
336bc174764SAziz IDOMAR 	if (status != MHU_V_3_X_ERR_NONE) {
337bc174764SAziz IDOMAR 		return status;
338bc174764SAziz IDOMAR 	}
339bc174764SAziz IDOMAR 
340bc174764SAziz IDOMAR 	/* Only doorbell channel is supported */
341bc174764SAziz IDOMAR 	if (ch_type != MHU_V3_X_CHANNEL_TYPE_DBCH) {
342bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_UNSUPPORTED;
343bc174764SAziz IDOMAR 	}
344bc174764SAziz IDOMAR 
345bc174764SAziz IDOMAR 	p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
346bc174764SAziz IDOMAR 
347bc174764SAziz IDOMAR 	if (dev->frame == MHU_V3_X_PBX_FRAME) {
348bc174764SAziz IDOMAR 		pdbcw_reg = (struct _mhu_v3_x_pdbcw_reg_t *)
349bc174764SAziz IDOMAR 			&(p_mhu->pbx_frame.pdbcw_page);
350bc174764SAziz IDOMAR 
351bc174764SAziz IDOMAR 		/*
352bc174764SAziz IDOMAR 		 * Enable this doorbell channel to generate interrupts for
353bc174764SAziz IDOMAR 		 * transfer acknowledge events.
354bc174764SAziz IDOMAR 		 */
355bc174764SAziz IDOMAR 		pdbcw_reg[channel].pdbcw_int_en = MHU_V3_X_PDBCW_INT_X_TFR_ACK;
356bc174764SAziz IDOMAR 
357bc174764SAziz IDOMAR 		/*
358bc174764SAziz IDOMAR 		 * Enable this doorbell channel to contribute to the PBX
359bc174764SAziz IDOMAR 		 * combined interrupt.
360bc174764SAziz IDOMAR 		 */
361bc174764SAziz IDOMAR 		pdbcw_reg[channel].pdbcw_ctrl = MHU_V3_X_PDBCW_CTRL_PBX_COMB_EN;
362bc174764SAziz IDOMAR 	} else if (dev->frame == MHU_V3_X_MBX_FRAME) {
363bc174764SAziz IDOMAR 		mdbcw_reg = (struct _mhu_v3_x_mdbcw_reg_t *)
364bc174764SAziz IDOMAR 			&(p_mhu->mbx_frame.mdbcw_page);
365bc174764SAziz IDOMAR 
366bc174764SAziz IDOMAR 		/*
367bc174764SAziz IDOMAR 		 * Enable this doorbell channel to contribute to the MBX
368bc174764SAziz IDOMAR 		 * combined interrupt.
369bc174764SAziz IDOMAR 		 */
370bc174764SAziz IDOMAR 		mdbcw_reg[channel].mdbcw_ctrl = MHU_V3_X_MDBCW_CTRL_MBX_COMB_EN;
371bc174764SAziz IDOMAR 	} else {
372bc174764SAziz IDOMAR 		/* Only PBX and MBX frames are supported. */
373bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_UNSUPPORTED;
374bc174764SAziz IDOMAR 	}
375bc174764SAziz IDOMAR 
376bc174764SAziz IDOMAR 	return MHU_V_3_X_ERR_NONE;
377bc174764SAziz IDOMAR }
378bc174764SAziz IDOMAR 
379bc174764SAziz IDOMAR enum mhu_v3_x_error_t mhu_v3_x_channel_interrupt_disable(
380bc174764SAziz IDOMAR 	 const struct mhu_v3_x_dev_t *dev, const uint32_t channel,
381bc174764SAziz IDOMAR 	 enum mhu_v3_x_channel_type_t ch_type)
382bc174764SAziz IDOMAR {
383bc174764SAziz IDOMAR 	enum mhu_v3_x_error_t status;
384bc174764SAziz IDOMAR 
385bc174764SAziz IDOMAR 	union _mhu_v3_x_frame_t *p_mhu;
386bc174764SAziz IDOMAR 	struct _mhu_v3_x_pdbcw_reg_t *pdbcw_reg;
387bc174764SAziz IDOMAR 	struct _mhu_v3_x_mdbcw_reg_t *mdbcw_reg;
388bc174764SAziz IDOMAR 
389bc174764SAziz IDOMAR 	/* Get dev->base if it is valid or return an error if dev is not */
390bc174764SAziz IDOMAR 	status = get_dev_base(dev, &p_mhu);
391bc174764SAziz IDOMAR 	if (status != MHU_V_3_X_ERR_NONE) {
392bc174764SAziz IDOMAR 		return status;
393bc174764SAziz IDOMAR 	}
394bc174764SAziz IDOMAR 
395bc174764SAziz IDOMAR 	/* Only doorbell channel is supported */
396bc174764SAziz IDOMAR 	if (ch_type != MHU_V3_X_CHANNEL_TYPE_DBCH) {
397bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_UNSUPPORTED;
398bc174764SAziz IDOMAR 	}
399bc174764SAziz IDOMAR 
400bc174764SAziz IDOMAR 	p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
401bc174764SAziz IDOMAR 
402bc174764SAziz IDOMAR 	if (dev->frame == MHU_V3_X_PBX_FRAME) {
403bc174764SAziz IDOMAR 		pdbcw_reg = (struct _mhu_v3_x_pdbcw_reg_t *)
404bc174764SAziz IDOMAR 			&(p_mhu->pbx_frame.pdbcw_page);
405bc174764SAziz IDOMAR 
406bc174764SAziz IDOMAR 		/* Clear channel transfer acknowledge event interrupt */
407bc174764SAziz IDOMAR 		pdbcw_reg[channel].pdbcw_int_clr = MHU_V3_X_PDBCW_INT_X_TFR_ACK;
408bc174764SAziz IDOMAR 
409bc174764SAziz IDOMAR 		/* Disable channel transfer acknowledge event interrupt */
410bc174764SAziz IDOMAR 		pdbcw_reg[channel].pdbcw_int_en &=
411bc174764SAziz IDOMAR 			~(MHU_V3_X_PDBCW_INT_X_TFR_ACK);
412bc174764SAziz IDOMAR 
413bc174764SAziz IDOMAR 		/*
414bc174764SAziz IDOMAR 		 * Disable this doorbell channel from contributing to the PBX
415bc174764SAziz IDOMAR 		 * combined interrupt.
416bc174764SAziz IDOMAR 		 */
417bc174764SAziz IDOMAR 		pdbcw_reg[channel].pdbcw_ctrl &=
418bc174764SAziz IDOMAR 			~(MHU_V3_X_PDBCW_CTRL_PBX_COMB_EN);
419bc174764SAziz IDOMAR 	} else if (dev->frame == MHU_V3_X_MBX_FRAME) {
420bc174764SAziz IDOMAR 		mdbcw_reg = (struct _mhu_v3_x_mdbcw_reg_t *)
421bc174764SAziz IDOMAR 			&(p_mhu->mbx_frame.mdbcw_page);
422bc174764SAziz IDOMAR 
423bc174764SAziz IDOMAR 		/*
424bc174764SAziz IDOMAR 		 * Disable this doorbell channel from contributing to the MBX
425bc174764SAziz IDOMAR 		 * combined interrupt.
426bc174764SAziz IDOMAR 		 */
427bc174764SAziz IDOMAR 		mdbcw_reg[channel].mdbcw_ctrl &=
428bc174764SAziz IDOMAR 			~(MHU_V3_X_MDBCW_CTRL_MBX_COMB_EN);
429bc174764SAziz IDOMAR 	} else {
430bc174764SAziz IDOMAR 		/* Only PBX and MBX frames are supported. */
431bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_UNSUPPORTED;
432bc174764SAziz IDOMAR 	}
433bc174764SAziz IDOMAR 
434bc174764SAziz IDOMAR 	return MHU_V_3_X_ERR_NONE;
435bc174764SAziz IDOMAR }
436bc174764SAziz IDOMAR 
437bc174764SAziz IDOMAR enum mhu_v3_x_error_t mhu_v3_x_channel_interrupt_clear(
438bc174764SAziz IDOMAR 	 const struct mhu_v3_x_dev_t *dev, const uint32_t channel,
439bc174764SAziz IDOMAR 	 enum mhu_v3_x_channel_type_t ch_type)
440bc174764SAziz IDOMAR {
441bc174764SAziz IDOMAR 	enum mhu_v3_x_error_t status;
442bc174764SAziz IDOMAR 	union _mhu_v3_x_frame_t *p_mhu;
443bc174764SAziz IDOMAR 	struct _mhu_v3_x_pdbcw_reg_t *pdbcw_reg;
444bc174764SAziz IDOMAR 
445bc174764SAziz IDOMAR 	/* Get dev->base if it is valid or return an error if dev is not */
446bc174764SAziz IDOMAR 	status = get_dev_base(dev, &p_mhu);
447bc174764SAziz IDOMAR 	if (status != MHU_V_3_X_ERR_NONE) {
448bc174764SAziz IDOMAR 		return status;
449bc174764SAziz IDOMAR 	}
450bc174764SAziz IDOMAR 
451bc174764SAziz IDOMAR 	/* Only doorbell channel is supported */
452bc174764SAziz IDOMAR 	if (ch_type != MHU_V3_X_CHANNEL_TYPE_DBCH) {
453bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_UNSUPPORTED;
454bc174764SAziz IDOMAR 	}
455bc174764SAziz IDOMAR 
456bc174764SAziz IDOMAR 	/*
457bc174764SAziz IDOMAR 	 * Only postbox doorbell channel transfer acknowledge interrupt can be
458bc174764SAziz IDOMAR 	 * cleared manually.
459bc174764SAziz IDOMAR 	 *
460bc174764SAziz IDOMAR 	 * To clear MBX interrupt the unmasked status must be cleared using
461bc174764SAziz IDOMAR 	 * mhu_v3_x_doorbell_clear.
462bc174764SAziz IDOMAR 	 */
463bc174764SAziz IDOMAR 	if (dev->frame != MHU_V3_X_PBX_FRAME) {
464bc174764SAziz IDOMAR 		return MHU_V_3_X_ERR_INVALID_PARAM;
465bc174764SAziz IDOMAR 	}
466bc174764SAziz IDOMAR 
467bc174764SAziz IDOMAR 	p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
468bc174764SAziz IDOMAR 	pdbcw_reg = (struct _mhu_v3_x_pdbcw_reg_t *)&(
469bc174764SAziz IDOMAR 			p_mhu->pbx_frame.pdbcw_page);
470bc174764SAziz IDOMAR 
471bc174764SAziz IDOMAR 	/* Clear channel transfer acknowledge event interrupt */
472bc174764SAziz IDOMAR 	pdbcw_reg[channel].pdbcw_int_clr |= 0x1;
473bc174764SAziz IDOMAR 
474bc174764SAziz IDOMAR 	return MHU_V_3_X_ERR_NONE;
475bc174764SAziz IDOMAR }
476