/***************************************************************************
 *
 * Copyright 2015-2019 BES.
 * All rights reserved. All unpublished rights reserved.
 *
 * No part of this work may be used or reproduced in any form or by any
 * means, or stored in a database or retrieval system, without prior written
 * permission of BES.
 *
 * Use of this work is governed by a license granted by BES.
 * This work contains confidential and proprietary information of
 * BES. which is protected by copyright, trade secret,
 * trademark and other intellectual property rights.
 *
 ****************************************************************************/
#ifdef CHIP_HAS_TRANSQ

#include "plat_addr_map.h"
#include "reg_transq.h"
#include "hal_transq.h"
#include "hal_trace.h"
#include "hal_cmu.h"
#include "stdbool.h"
#include "cmsis_nvic.h"

// BITMAP:
// [High Priority Slots] ...... [Normal Priority Slots]
// 31 30 29 28 27 26 25  ...... 10 9 8 7 6 5 4 3 2 1 0

static struct TRANSQ_T * const transq[HAL_TRANSQ_ID_QTY] = {
    (struct TRANSQ_T *)TRANSQ0_BASE,
#if (CHIP_HAS_TRANSQ > 1)
    (struct TRANSQ_T *)TRANSQ1_BASE,
#endif
};

static struct TRANSQ_T * const peer_transq[HAL_TRANSQ_ID_QTY] = {
    (struct TRANSQ_T *)TRANSQ0_PEER_BASE,
#if (CHIP_HAS_TRANSQ > 1)
    (struct TRANSQ_T *)TRANSQ1_PEER_BASE,
#endif
};

static const IRQn_Type remote_irq_num[HAL_TRANSQ_ID_QTY] = {
    TRANSQ0_RMT_IRQn,
#if (CHIP_HAS_TRANSQ > 1)
    TRANSQ1_RMT_IRQn,
#endif
};

static const IRQn_Type local_irq_num[HAL_TRANSQ_ID_QTY] = {
    TRANSQ0_LCL_IRQn,
#if (CHIP_HAS_TRANSQ > 1)
    TRANSQ1_LCL_IRQn,
#endif
};

static struct HAL_TRANSQ_CFG_T transq_cfg[HAL_TRANSQ_ID_QTY];

static uint8_t next_tx_slot[HAL_TRANSQ_ID_QTY][HAL_TRANSQ_PRI_QTY];

static uint8_t active_tx_slot[HAL_TRANSQ_ID_QTY][HAL_TRANSQ_PRI_QTY];

static bool tx_slot_full[HAL_TRANSQ_ID_QTY][HAL_TRANSQ_PRI_QTY];

static uint8_t next_rx_slot[HAL_TRANSQ_ID_QTY][HAL_TRANSQ_PRI_QTY];

static uint32_t rx_irq_mask[HAL_TRANSQ_ID_QTY][HAL_TRANSQ_PRI_QTY];

static uint32_t construct_mask(uint32_t lsb, uint32_t width)
{
    int i;
    uint32_t result;

    if (lsb >= 32 || width == 0) {
        return 0;
    }

    result = 0;
    for (i = lsb; i < lsb + width; i++) {
        result |= (1 << i);
    }

    return result;
}

static uint32_t get_next_rx_slot(enum HAL_TRANSQ_ID_T id, enum HAL_TRANSQ_PRI_T pri, uint32_t slot)
{
    slot++;
    if (pri == HAL_TRANSQ_PRI_HIGH) {
        if (slot >= TRANSQ_SLOT_NUM) {
            slot = TRANSQ_SLOT_NUM - transq_cfg[id].slot.rx_num[pri];
        }
    } else {
        if (slot >= transq_cfg[id].slot.rx_num[pri]) {
            slot = 0;
        }
    }

    return slot;
}

static uint32_t get_next_tx_slot(enum HAL_TRANSQ_ID_T id, enum HAL_TRANSQ_PRI_T pri, uint32_t slot)
{
    slot++;
    if (pri == HAL_TRANSQ_PRI_HIGH) {
        if (slot >= TRANSQ_SLOT_NUM) {
            slot = TRANSQ_SLOT_NUM - transq_cfg[id].slot.tx_num[pri];
        }
    } else {
        if (slot >= transq_cfg[id].slot.tx_num[pri]) {
            slot = 0;
        }
    }

    return slot;
}

static void hal_transq_remote_irq_handler(void)
{
    enum HAL_TRANSQ_ID_T id;
    enum HAL_TRANSQ_PRI_T pri;
    uint32_t status;
    uint32_t slot;

#if (CHIP_HAS_TRANSQ > 1)
    IRQn_Type irq = NVIC_GetCurrentActiveIRQ();

    for (id = HAL_TRANSQ_ID_0; id < HAL_TRANSQ_ID_QTY; id++) {
        if (irq == remote_irq_num[id]) {
            break;
        }
    }
    if (id >= HAL_TRANSQ_ID_QTY) {
        return;
    }
#else
    id = HAL_TRANSQ_ID_0;
#endif

    while ((status = peer_transq[id]->RMT_MIS) != 0) {
        slot = next_rx_slot[id][HAL_TRANSQ_PRI_HIGH];
        if (slot < TRANSQ_SLOT_NUM && (status & (1 << slot))) {
            pri = HAL_TRANSQ_PRI_HIGH;
        } else {
            pri = HAL_TRANSQ_PRI_NORMAL;
            slot = next_rx_slot[id][HAL_TRANSQ_PRI_NORMAL];

            ASSERT(slot < TRANSQ_SLOT_NUM && (status & (1 << slot)),
                "TRANSQ-%d: Rx IRQ when no slot or out of order: status=0x%08x next=%d pri_next=%d",
                id, status, next_rx_slot[id][HAL_TRANSQ_PRI_NORMAL], next_rx_slot[id][HAL_TRANSQ_PRI_HIGH]);
        }

        // Mask IRQ from corresponding slots
        peer_transq[id]->RMT_INTMASK &= ~rx_irq_mask[id][pri];

        if (transq_cfg[id].rx_handler) {
            transq_cfg[id].rx_handler(pri);
        }
    }
}

static int hal_transq_active_tx_valid(enum HAL_TRANSQ_ID_T id, enum HAL_TRANSQ_PRI_T pri)
{
    return (active_tx_slot[id][pri] >= TRANSQ_SLOT_NUM ||
            active_tx_slot[id][pri] != next_tx_slot[id][pri] ||
            tx_slot_full[id][pri]);
}

static void hal_transq_local_irq_handler(void)
{
    enum HAL_TRANSQ_ID_T id;
    enum HAL_TRANSQ_PRI_T pri;
    uint32_t status;
    uint32_t slot, next_slot;
    uint32_t lock;

#if (CHIP_HAS_TRANSQ > 1)
    IRQn_Type irq = NVIC_GetCurrentActiveIRQ();

    for (id = HAL_TRANSQ_ID_0; id < HAL_TRANSQ_ID_QTY; id++) {
        if (irq == local_irq_num[id]) {
            break;
        }
    }
    if (id >= HAL_TRANSQ_ID_QTY) {
        return;
    }
#else
    id = HAL_TRANSQ_ID_0;
#endif

    while ((status = transq[id]->LERR_MIS) != 0) {
        transq[id]->LERR_ISC.LERR_INTCLR = status;
        ASSERT(false, "TRANSQ-%d: Tx on active slot: 0x%08x", id, status);
    }

    while ((status = transq[id]->LDONE_MIS) != 0) {
        if (transq_cfg[id].tx_handler) {
            lock = int_lock();

            ASSERT(hal_transq_active_tx_valid(id, HAL_TRANSQ_PRI_HIGH), "TRANSQ-%d: Corrupted pri active tx: active=%d next=%d full=%d",
                id, active_tx_slot[id][HAL_TRANSQ_PRI_HIGH], next_tx_slot[id][HAL_TRANSQ_PRI_HIGH], tx_slot_full[id][HAL_TRANSQ_PRI_HIGH]);
            ASSERT(hal_transq_active_tx_valid(id, HAL_TRANSQ_PRI_NORMAL), "TRANSQ-%d: Corrupted active tx: active=%d next=%d full=%d",
                id, active_tx_slot[id][HAL_TRANSQ_PRI_NORMAL], next_tx_slot[id][HAL_TRANSQ_PRI_NORMAL], tx_slot_full[id][HAL_TRANSQ_PRI_NORMAL]);

            slot = active_tx_slot[id][HAL_TRANSQ_PRI_HIGH];
            if (slot < TRANSQ_SLOT_NUM && (status & (1 << slot))) {
                pri = HAL_TRANSQ_PRI_HIGH;
            } else {
                pri = HAL_TRANSQ_PRI_NORMAL;
                slot = active_tx_slot[id][HAL_TRANSQ_PRI_NORMAL];

                ASSERT(slot < TRANSQ_SLOT_NUM && (status & (1 << slot)),
                    "TRANSQ-%d: Tx done IRQ when slot empty or out of order: status=0x%08x next=%d pri_next=%d",
                    id, status, active_tx_slot[id][HAL_TRANSQ_PRI_NORMAL], active_tx_slot[id][HAL_TRANSQ_PRI_HIGH]);
            }

            // Clear the interrupt
            transq[id]->LDONE_ISC.LDONE_INTCLR = (1 << slot);

            next_slot = get_next_tx_slot(id, pri, slot);

            if (!tx_slot_full[id][pri] && next_slot == next_tx_slot[id][pri]) {
                // No tx in progress
                active_tx_slot[id][pri] = TRANSQ_SLOT_NUM;
            } else {
                tx_slot_full[id][pri] = false;
                if (transq_cfg[id].slot.tx_num[pri] == 1) {
                    // No tx in progress
                    active_tx_slot[id][pri] = TRANSQ_SLOT_NUM;
                } else {
                    // Some tx in progress
                    active_tx_slot[id][pri] = next_slot;
                }
            }

            int_unlock(lock);

            transq_cfg[id].tx_handler(pri,
                (const uint8_t *)transq[id]->WSLOT[slot].ADDR,
                transq[id]->WSLOT[slot].LEN);
        } else {
            transq[id]->LDONE_INTMASK = 0;
        }
    }
}

enum HAL_TRANSQ_RET_T hal_transq_get_rx_status(enum HAL_TRANSQ_ID_T id, enum HAL_TRANSQ_PRI_T pri, bool *ready)
{
    uint32_t lock;
    uint32_t slot;

    if (id >= HAL_TRANSQ_ID_QTY) {
        return HAL_TRANSQ_RET_BAD_ID;
    }
    if (pri >= HAL_TRANSQ_PRI_QTY) {
        return HAL_TRANSQ_RET_BAD_PRI;
    }
    if (transq_cfg[id].slot.rx_num[pri] == 0) {
        return HAL_TRANSQ_RET_BAD_RX_NUM;
    }
    if (transq_cfg[id].rx_handler) {
        // Rx will be processed by IRQ handler
        return HAL_TRANSQ_RET_BAD_MODE;
    }

    lock = int_lock();

    slot = next_rx_slot[id][pri];

    if (slot < TRANSQ_SLOT_NUM && peer_transq[id]->RMT_ISC.RMT_RIS & (1 << slot)) {
        *ready = true;
    } else {
        *ready = false;
    }

    int_unlock(lock);

    return HAL_TRANSQ_RET_OK;
}

enum HAL_TRANSQ_RET_T hal_transq_get_tx_status(enum HAL_TRANSQ_ID_T id, enum HAL_TRANSQ_PRI_T pri, bool *done)
{
    uint32_t lock;
    uint32_t slot, next_slot;

    if (id >= HAL_TRANSQ_ID_QTY) {
        return HAL_TRANSQ_RET_BAD_ID;
    }
    if (pri >= HAL_TRANSQ_PRI_QTY) {
        return HAL_TRANSQ_RET_BAD_PRI;
    }
    if (transq_cfg[id].slot.tx_num[pri] == 0) {
        return HAL_TRANSQ_RET_BAD_TX_NUM;
    }
    if (transq_cfg[id].tx_handler) {
        // Tx done will be processed by IRQ handler
        return HAL_TRANSQ_RET_BAD_MODE;
    }

    lock = int_lock();

    slot = active_tx_slot[id][pri];

    ASSERT(hal_transq_active_tx_valid(id, pri), "TRANSQ-%d: Corrupted active tx: pri=%d active=%d next=%d full=%d",
        id, pri, active_tx_slot[id][pri], next_tx_slot[id][pri], tx_slot_full[id][pri]);

    if (transq[id]->LDONE_ISC.LDONE_RIS & (1 << slot)) {
        *done = true;

        // Clear the interrupt
        transq[id]->LDONE_ISC.LDONE_INTCLR = (1 << slot);

        next_slot = get_next_tx_slot(id, pri, slot);

        if (!tx_slot_full[id][pri] && next_slot == next_tx_slot[id][pri]) {
            // No tx in progress
            active_tx_slot[id][pri] = TRANSQ_SLOT_NUM;
        } else {
            tx_slot_full[id][pri] = false;
            if (transq_cfg[id].slot.tx_num[pri] == 1) {
                // No tx in progress
                active_tx_slot[id][pri] = TRANSQ_SLOT_NUM;
            } else {
                // Some tx in progress
                active_tx_slot[id][pri] = next_slot;
            }
        }
    } else {
        *done = false;
    }

    int_unlock(lock);

    return HAL_TRANSQ_RET_OK;
}

enum HAL_TRANSQ_RET_T hal_transq_rx_first(enum HAL_TRANSQ_ID_T id, enum HAL_TRANSQ_PRI_T pri, const uint8_t **data, uint32_t *len)
{
    enum HAL_TRANSQ_RET_T ret;
    uint32_t slot;
    //uint32_t lock;

    if (id >= HAL_TRANSQ_ID_QTY) {
        return HAL_TRANSQ_RET_BAD_ID;
    }
    if (pri >= HAL_TRANSQ_PRI_QTY) {
        return HAL_TRANSQ_RET_BAD_PRI;
    }
    if (transq_cfg[id].slot.rx_num[pri] == 0) {
        return HAL_TRANSQ_RET_BAD_RX_NUM;
    }

    //lock = int_lock();

    slot = next_rx_slot[id][pri];

    if (slot < TRANSQ_SLOT_NUM && peer_transq[id]->RMT_ISC.RMT_RIS & (1 << slot)) {
        // Msg available
        ret = HAL_TRANSQ_RET_OK;

        if (data) {
            *data = (const uint8_t *)peer_transq[id]->RSLOT[slot].ADDR;
        }
        if (len) {
            *len = peer_transq[id]->RSLOT[slot].LEN;
        }
    } else {
        // No msg. Re-enable IRQ
        ret = HAL_TRANSQ_RET_RX_EMPTY;

        if (data) {
            *data = NULL;
        }
        if (len) {
            *len = 0;
        }
        peer_transq[id]->RMT_INTMASK |= rx_irq_mask[id][pri];
    }

    //int_unlock(lock);

    return ret;
}

enum HAL_TRANSQ_RET_T hal_transq_rx_next(enum HAL_TRANSQ_ID_T id, enum HAL_TRANSQ_PRI_T pri, const uint8_t **data, uint32_t *len)
{
    enum HAL_TRANSQ_RET_T ret;
    uint32_t slot;
    //uint32_t lock;

    if (id >= HAL_TRANSQ_ID_QTY) {
        return HAL_TRANSQ_RET_BAD_ID;
    }
    if (pri >= HAL_TRANSQ_PRI_QTY) {
        return HAL_TRANSQ_RET_BAD_PRI;
    }
    if (transq_cfg[id].slot.rx_num[pri] == 0) {
        return HAL_TRANSQ_RET_BAD_RX_NUM;
    }

    ret = HAL_TRANSQ_RET_OK;

    //lock = int_lock();

    slot = next_rx_slot[id][pri];

    if (slot < TRANSQ_SLOT_NUM && peer_transq[id]->RMT_ISC.RMT_RIS & (1 << slot)) {
        // Clear cur IRQ
        peer_transq[id]->RMT_ISC.RMT_INTCLR = (1 << slot);

        // Update next_rx_slot
        slot = get_next_rx_slot(id, pri, slot);
        next_rx_slot[id][pri] = slot;

        if (slot < TRANSQ_SLOT_NUM && peer_transq[id]->RMT_ISC.RMT_RIS & (1 << slot)) {
            // Next msg available
            if (data) {
                *data = (const uint8_t *)peer_transq[id]->RSLOT[slot].ADDR;
            }
            if (len) {
                *len = peer_transq[id]->RSLOT[slot].LEN;
            }
        } else {
            // No msg
            ret = HAL_TRANSQ_RET_RX_EMPTY;
        }
    } else {
        // No msg
        ret = HAL_TRANSQ_RET_RX_EMPTY;
    }

    if (ret == HAL_TRANSQ_RET_RX_EMPTY) {
        if (data) {
            *data = NULL;
        }
        if (len) {
            *len = 0;
        }
        // Re-enable IRQ
        peer_transq[id]->RMT_INTMASK |= rx_irq_mask[id][pri];
    }

    //int_unlock(lock);

    return ret;
}

enum HAL_TRANSQ_RET_T hal_transq_tx(enum HAL_TRANSQ_ID_T id, enum HAL_TRANSQ_PRI_T pri, const uint8_t *data, uint32_t len)
{
    enum HAL_TRANSQ_RET_T ret;
    uint32_t lock;
    uint32_t slot;

    if (id >= HAL_TRANSQ_ID_QTY) {
        return HAL_TRANSQ_RET_BAD_ID;
    }
    if (pri >= HAL_TRANSQ_PRI_QTY) {
        return HAL_TRANSQ_RET_BAD_PRI;
    }
    if (transq_cfg[id].slot.tx_num[pri] == 0) {
        return HAL_TRANSQ_RET_BAD_TX_NUM;
    }

    lock = int_lock();

    if (tx_slot_full[id][pri]) {
        ret = HAL_TRANSQ_RET_TX_FULL;
    } else {
        ret = HAL_TRANSQ_RET_OK;

        slot = next_tx_slot[id][pri];

        transq[id]->WSLOT[slot].ADDR = (uint32_t)data;
        transq[id]->WSLOT[slot].LEN = len;
        transq[id]->RMT_INTSET = (1 << slot);

        // Update active_tx_slot if this is the only tx in progress
        if (active_tx_slot[id][pri] >= TRANSQ_SLOT_NUM) {
            active_tx_slot[id][pri] = slot;
        }

        // Update next_tx_slot
        next_tx_slot[id][pri] = get_next_tx_slot(id, pri, slot);

        if (next_tx_slot[id][pri] == active_tx_slot[id][pri]) {
            tx_slot_full[id][pri] = true;
        }
    }

    int_unlock(lock);

    return ret;
}

enum HAL_TRANSQ_RET_T hal_transq_update_num(enum HAL_TRANSQ_ID_T id, const struct HAL_TRANSQ_SLOT_NUM_T *slot)
{
    uint32_t tx_mask;

    if (id >= HAL_TRANSQ_ID_QTY) {
        return HAL_TRANSQ_RET_BAD_ID;
    }
    if (slot == NULL) {
        return HAL_TRANSQ_RET_BAD_SLOT;
    }
    if (slot->tx_num[HAL_TRANSQ_PRI_NORMAL] + slot->tx_num[HAL_TRANSQ_PRI_HIGH] > TRANSQ_SLOT_NUM) {
        return HAL_TRANSQ_RET_BAD_TX_NUM;
    }
    if (slot->rx_num[HAL_TRANSQ_PRI_NORMAL] + slot->rx_num[HAL_TRANSQ_PRI_HIGH] > TRANSQ_SLOT_NUM) {
        return HAL_TRANSQ_RET_BAD_RX_NUM;
    }

    transq_cfg[id].slot = *slot;

    rx_irq_mask[id][HAL_TRANSQ_PRI_NORMAL] = construct_mask(0, slot->rx_num[HAL_TRANSQ_PRI_NORMAL]);
    rx_irq_mask[id][HAL_TRANSQ_PRI_HIGH] = construct_mask(
        TRANSQ_SLOT_NUM - slot->rx_num[HAL_TRANSQ_PRI_HIGH],
        slot->rx_num[HAL_TRANSQ_PRI_HIGH]);

    tx_mask = construct_mask(0, slot->tx_num[HAL_TRANSQ_PRI_NORMAL]) |
        construct_mask(TRANSQ_SLOT_NUM - slot->tx_num[HAL_TRANSQ_PRI_HIGH], slot->tx_num[HAL_TRANSQ_PRI_HIGH]);

    transq[id]->RMT_INTMASK = tx_mask;
    transq[id]->LERR_INTMASK = tx_mask;
    if (transq_cfg[id].tx_handler) {
        transq[id]->LDONE_INTMASK = tx_mask;
    } else {
        transq[id]->LDONE_INTMASK = 0;
    }

    return HAL_TRANSQ_RET_OK;
}

enum HAL_TRANSQ_RET_T hal_transq_open(enum HAL_TRANSQ_ID_T id, const struct HAL_TRANSQ_CFG_T *cfg)
{
    const struct HAL_TRANSQ_SLOT_NUM_T *slot;
    uint32_t ctrl;
    enum HAL_TRANSQ_RET_T ret;

    if (id >= HAL_TRANSQ_ID_QTY) {
        return HAL_TRANSQ_RET_BAD_ID;
    }
    if (cfg == NULL) {
        return HAL_TRANSQ_RET_BAD_CFG;
    }

#ifdef CHIP_BEST2000
    hal_cmu_clock_enable(HAL_CMU_MOD_P_TRANSQ_WF);
    hal_cmu_reset_clear(HAL_CMU_MOD_P_TRANSQ_WF);
#elif defined(CHIP_BEST2001) && !defined(CHIP_BEST2001_DSP)
    //2001 dsp has enable transq clk at hal_cmu_dsp_clock_enable()
    hal_cmu_clock_enable(HAL_CMU_MOD_P_TQWF);
    hal_cmu_reset_clear(HAL_CMU_MOD_P_TQWF);
    hal_cmu_clock_enable(HAL_CMU_MOD_P_TQA7);
    hal_cmu_reset_clear(HAL_CMU_MOD_P_TQA7);
#endif

    transq_cfg[id] = *cfg;

    slot = &cfg->slot;

    ret = hal_transq_update_num(id, slot);
    if (ret) {
        return ret;
    }

    next_tx_slot[id][HAL_TRANSQ_PRI_NORMAL] = slot->tx_num[HAL_TRANSQ_PRI_NORMAL] ? 0 : TRANSQ_SLOT_NUM;
    active_tx_slot[id][HAL_TRANSQ_PRI_NORMAL] = TRANSQ_SLOT_NUM;
    tx_slot_full[id][HAL_TRANSQ_PRI_NORMAL] = false;
    next_rx_slot[id][HAL_TRANSQ_PRI_NORMAL] = slot->rx_num[HAL_TRANSQ_PRI_NORMAL] ? 0 : TRANSQ_SLOT_NUM;

    next_tx_slot[id][HAL_TRANSQ_PRI_HIGH] = slot->tx_num[HAL_TRANSQ_PRI_HIGH] ?
        (TRANSQ_SLOT_NUM - slot->tx_num[HAL_TRANSQ_PRI_HIGH]) : TRANSQ_SLOT_NUM;
    active_tx_slot[id][HAL_TRANSQ_PRI_HIGH] = TRANSQ_SLOT_NUM;
    tx_slot_full[id][HAL_TRANSQ_PRI_HIGH] = false;
    next_rx_slot[id][HAL_TRANSQ_PRI_HIGH] = slot->rx_num[HAL_TRANSQ_PRI_HIGH] ?
        (TRANSQ_SLOT_NUM - slot->rx_num[HAL_TRANSQ_PRI_HIGH]) : TRANSQ_SLOT_NUM;

    transq[id]->LDONE_ISC.LDONE_INTCLR = ~0UL;
    transq[id]->LERR_ISC.LERR_INTCLR = ~0UL;
    transq[id]->RMT_ISC.RMT_INTCLR = ~0UL;

    ctrl = CTRL_REMOTE_IRQ_EN | CTRL_LOCAL_ERR_IRQ_EN;
    if (cfg->tx_handler) {
        ctrl |= CTRL_LOCAL_DONE_IRQ_EN;
    }
    transq[id]->CTRL = ctrl;

    if (cfg->rx_handler) {
        NVIC_SetVector(remote_irq_num[id], (uint32_t)hal_transq_remote_irq_handler);
        NVIC_SetPriority(remote_irq_num[id], IRQ_PRIORITY_NORMAL);
        NVIC_ClearPendingIRQ(remote_irq_num[id]);
        NVIC_EnableIRQ(remote_irq_num[id]);
    }

    NVIC_SetVector(local_irq_num[id], (uint32_t)hal_transq_local_irq_handler);
    NVIC_SetPriority(local_irq_num[id], IRQ_PRIORITY_NORMAL);
    NVIC_ClearPendingIRQ(local_irq_num[id]);
    NVIC_EnableIRQ(local_irq_num[id]);

    return HAL_TRANSQ_RET_OK;
}

enum HAL_TRANSQ_RET_T hal_transq_close(enum HAL_TRANSQ_ID_T id)
{
    if (id >= HAL_TRANSQ_ID_QTY) {
        return HAL_TRANSQ_RET_BAD_ID;
    }

    transq[id]->CTRL = 0;
    NVIC_DisableIRQ(remote_irq_num[id]);
    NVIC_DisableIRQ(local_irq_num[id]);

    return HAL_TRANSQ_RET_OK;
}

#endif // CHIP_HAS_TRANSQ
