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