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