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