blob: c985ad02ab6d1feb9f16df69bf0427153a13b6ee [file] [log] [blame]
/*****************************************************************************
* Copyright Statement:
* --------------------
* This software is protected by Copyright and the information contained
* herein is confidential. The software may not be copied and the information
* contained herein may not be used or disclosed except with the written
* permission of MediaTek Inc. (C) 2018
*
* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
*
* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
*
* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
*
*****************************************************************************/
/*****************************************************************************
*
* Filename:
* ---------
* kal_itc.h
*
* Project:
* --------
* UMOLYE
*
* Description:
* ------------
* This file provides KAL ITC related APIs
*
* Author:
* -------
* -------
*
*============================================================================
* HISTORY
* Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
*------------------------------------------------------------------------------
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
*
****************************************************************************/
#ifndef _KAL_ITC_H
#define _KAL_ITC_H
/*******************************************************************************
* Include Statements
*******************************************************************************/
#include "kal_general_types.h"
#include "kal_public_defs.h"
/*******************************************************************************
* Definitions and macros
*******************************************************************************/
#ifdef __MTK_TARGET__
#define KAL_SPINLOCK_CREATEDLIST
#endif
#ifndef HW_ITC_GRP
#if defined(__MD93__)
#define KAL_ITC_GRP 3 /* Context takes ITC */
#elif defined(__MD95__)
#define KAL_ITC_GRP 3 /* Context takes ITC */
#elif defined(__MD97__)
#define KAL_ITC_GRP 2 /* Context takes ITC, or Critical HRT LISR */
#elif defined(__MD97P__)
#define KAL_ITC_GRP 2 /* For now, MD97P defs same as in MD97 */
#else
#warning "unknown MDMCU version"
#endif
#else
#define KAL_ITC_GRP HW_ITC_GRP /* Context takes ITC */
#endif
#define KAL_ITC_MAX_NAME (8)
#define KAL_SPIN_LOCK_ID 0x53504c4bUL
/* Select correct DI API to use based on the current domain and VPE */
#define KAL_ITC_DI(ret_addr, is_hrt) \
({ \
kal_int32 _irq_state; \
if (is_hrt == KAL_TRUE) { \
_irq_state = kal_hrt_SaveAndSetIRQMask_ITC(ret_addr); \
} else { \
_irq_state = SaveAndSetIRQMask(); \
} \
_irq_state; \
})
/* Select correct EI API to use based on the current context and VPE */
#define KAL_ITC_EI(irq_state, ret_addr, is_hrt) \
do { \
if (is_hrt == KAL_TRUE) { \
kal_hrt_RestoreIRQMask_ITC(irq_state, ret_addr); \
} else { \
RestoreIRQMask(irq_state); \
} \
} while (0)
/* Primitive macro for taking the lock, return only after getting the lock */
#if defined(__mips16) || defined(__nanomips__)
#define KAL_ITC_LOCK_TAKE(lock) \
({ \
kal_status _ret = 0; \
__asm__ __volatile__( \
"1: ll %1, %2;" \
" beqz %1, 2f;" \
" pause;" \
" b 1b;" \
"2: li %1, 1;" \
" sc %1, %0;" \
" beqz %1, 1b;" \
: "=ZC"(lock), "+d"(_ret) \
: "ZC"(lock) \
: "memory"); \
_ret; \
})
#else
#define KAL_ITC_LOCK_TAKE(lock) \
({ \
kal_status _ret = 0; \
__asm__ __volatile__( \
" .set push;" \
" .set noreorder;" \
"1: ll %1, %2;" \
" beqz %1, 2f;" \
" li %1, 1;" \
" pause;" \
" b 1b;" \
" nop;" \
"2: sc %1, %0;" \
" beqz %1, 1b;" \
" nop;" \
" .set pop;" \
: "=ZC"(lock), "+d"(_ret) \
: "ZC"(lock) \
: "memory"); \
_ret; \
})
#endif
/* Primitive macro for taking the lock, return only after getting the lock,
* does disable interrupts.
* Old irq status saved in irq_mask */
#if defined(__mips16) || defined(__nanomips__)
#define KAL_ITC_LOCK_TAKE_DI(lock, irq_mask) \
({ \
kal_status _ret = 0; \
__asm__ __volatile__( \
" di %2;" \
" ehb;" \
" ext %2, %2, 0, 1;" \
"1: ll %1, %3;" \
" beqz %1, 3f;" \
" beqz %2, 2f;" \
" ei;" \
"2: pause;" \
" di %2;" \
" ehb;" \
" ext %2, %2, 0, 1;" \
" b 1b;" \
"3: li %1, 1;" \
" sc %1, %0;" \
" beqz %1, 1b;" \
: "=ZC"(lock), "+d"(_ret), "+d"(irq_mask) \
: "ZC"(lock) \
: "memory"); \
_ret; \
})
#else
#define KAL_ITC_LOCK_TAKE_DI(lock, irq_mask) \
({ \
kal_status _ret = 0; \
__asm__ __volatile__( \
" .set push;" \
" .set noreorder;" \
" di %2;" \
" ehb;" \
" ext %2, %2, 0, 1;" \
"1: ll %1, %3;" \
" beqz %1, 3f;" \
" li %1, 1;" \
" beqz %2, 2f;" \
" nop;" \
" ei;" \
"2: pause;" \
" di %2;" \
" ehb;" \
" ext %2, %2, 0, 1;" \
" b 1b;" \
" nop;" \
"3: sc %1, %0;" \
" beqz %1, 1b;" \
" nop;" \
" .set pop;" \
: "=ZC"(lock), "+d"(_ret), "+d"(irq_mask) \
: "ZC"(lock) \
: "memory"); \
_ret; \
})
#endif
/* Primitive macro for trying the lock, return success or fail */
#if defined(__mips16) || defined(__nanomips__)
#define KAL_ITC_LOCK_TRY(lock) \
({ \
kal_status _ret = 0; \
__asm__ __volatile__( \
" ll %1, %2;" \
" bnez %1, 1f;" \
" li %1, 1;" \
" sc %1, %0;" \
" b 2f;" \
"1: li %1, 0;" \
"2: ;" \
: "=ZC"(lock), "+d"(_ret) \
: "ZC"(lock) \
: "memory"); \
_ret = _ret != 0 ? KAL_SUCCESS : KAL_ERROR; \
_ret; \
})
#else
#define KAL_ITC_LOCK_TRY(lock) \
({ \
kal_status _ret = 0; \
__asm__ __volatile__( \
" .set push;" \
" .set noreorder;" \
" ll %1, %2;" \
" bnez %1, 1f;" \
" li %1, 0;" \
" li %1, 1;" \
" sc %1, %0;" \
"1: ;" \
" .set pop;" \
: "=ZC"(lock), "+d"(_ret) \
: "ZC"(lock) \
: "memory"); \
_ret = _ret != 0 ? KAL_SUCCESS : KAL_ERROR; \
_ret; \
})
#endif
/* Primitive macro for trying the lock, return success or fail,
* does disable interrupts if success.
* Old irq status saved in irq_mask */
#if defined(__mips16) || defined(__nanomips__)
#define KAL_ITC_LOCK_TRY_DI(lock, irq_mask) \
({ \
kal_status _ret = 0; \
__asm__ __volatile__( \
" di %2;" \
" ehb;" \
" ext %2, %2, 0, 1;" \
" ll %1, %3;" \
" bnez %1, 1f;" \
" li %1, 1;" \
" sc %1, %0;" \
" b 2f;" \
"1: li %1, 0;" \
"2: ;" \
: "=ZC"(lock), "+d"(_ret), "+d"(irq_mask) \
: "ZC"(lock) \
: "memory"); \
if (_ret != 0) { \
_ret = KAL_SUCCESS; \
} else { \
_ret = KAL_ERROR; \
if (irq_mask != 0) { \
__asm__ __volatile__("ei; ehb;" ::: "memory"); \
} \
} \
_ret; \
})
#else
#define KAL_ITC_LOCK_TRY_DI(lock, irq_mask) \
({ \
kal_status _ret = 0; \
__asm__ __volatile__( \
" .set push;" \
" .set noreorder;" \
" di %2;" \
" ehb;" \
" ext %2, %2, 0, 1;" \
" ll %1, %3;" \
" bnez %1, 1f;" \
" li %1, 0;" \
" li %1, 1;" \
" sc %1, %0;" \
"1: ;" \
" .set pop;" \
: "=ZC"(lock), "+d"(_ret), "+d"(irq_mask) \
: "ZC"(lock) \
: "memory"); \
if (_ret != 0) { \
_ret = KAL_SUCCESS; \
} else { \
_ret = KAL_ERROR; \
if (irq_mask != 0) { \
__asm__ __volatile__("ei; ehb;" ::: "memory"); \
} \
} \
_ret; \
})
#endif
/* Primitive macro for taking the lock, return only after getting the lock,
* does disable interrupts and disable MT.
* Old irq status saved in irq_mask, old MT status saved in mt_mask */
#if defined(__mips16) || defined(__nanomips__)
#define KAL_ITC_LOCK_TAKE_DI_DMT(lock, irq_mask, mt_mask) \
({ \
kal_status _ret = 0; \
__asm__ __volatile__( \
" dmt %3;" \
" ehb;" \
" di %2;" \
" ehb;" \
" ext %3, %3, 15, 1;" \
" ext %2, %2, 0, 1;" \
"1: ll %1, %4;" \
" beqz %1, 4f;" \
" beqz %2, 2f;" \
" ei;" \
"2: beqz %3, 3f;" \
" emt;" \
" ehb;" \
"3: pause;" \
" dmt %3;" \
" ehb;" \
" di %2;" \
" ehb;" \
" ext %3, %3, 15, 1;" \
" ext %2, %2, 0, 1;" \
" b 1b;" \
"4: li %1, 1;" \
" sc %1, %0;" \
" beqz %1, 1b;" \
: "=ZC" (lock), "+d" (_ret), "+d" (irq_mask), "+d" (mt_mask) \
: "ZC" (lock) \
: "memory" \
); \
_ret; \
})
#else
#define KAL_ITC_LOCK_TAKE_DI_DMT(lock, irq_mask, mt_mask) \
({ \
kal_status _ret = 0; \
__asm__ __volatile__( \
" .set push;" \
" .set noreorder;" \
" dmt %3;" \
" ehb;" \
" di %2;" \
" ehb;" \
" ext %3, %3, 15, 1;" \
" ext %2, %2, 0, 1;" \
"1: ll %1, %4;" \
" beqz %1, 4f;" \
" li %1, 1;" \
" beqz %2, 2f;" \
" nop;" \
" ei;" \
"2: beqz %2, 3f;" \
" nop;" \
" emt;" \
" ehb;" \
"3: pause;" \
" dmt %3;" \
" ehb;" \
" di %2;" \
" ehb;" \
" ext %3, %3, 15, 1;" \
" ext %2, %2, 0, 1;" \
" b 1b;" \
" nop;" \
"4: sc %1, %0;" \
" beqz %1, 1b;" \
" nop;" \
" .set pop;" \
: "=ZC" (lock), "+d" (_ret), "+d" (irq_mask), "+d" (mt_mask) \
: "ZC" (lock) \
: "memory" \
); \
_ret; \
})
#endif
/* Primitive macro for trying the lock, return success or fail,
* does disable interrupts and MT if success.
* Old irq status saved in irq_mask, old MT status saved in mt_mask */
#if defined(__mips16) || defined(__nanomips__)
#define KAL_ITC_LOCK_TRY_DI_DMT(lock, irq_maski, mt_mask) \
({ \
kal_status _ret = 0; \
__asm__ __volatile__( \
" dmt %3;" \
" ehb;" \
" di %2;" \
" ehb;" \
" ext %3, %3, 15, 1;" \
" ext %2, %2, 0, 1;" \
" ll %1, %4;" \
" bnez %1, 1f;" \
" li %1, 1;" \
" sc %1, %0;" \
" b 2f;" \
"1: li %1, 0;" \
"2: ;" \
: "=ZC" (lock), "+d" (_ret), "+d" (irq_mask), "+d" (mt_mask) \
: "ZC" (lock) \
: "memory" \
); \
if (_ret != 0) { \
_ret = KAL_SUCCESS; \
} else { \
_ret = KAL_ERROR; \
if (irq_mask != 0) { \
__asm__ __volatile__("ei; ehb;":::"memory"); \
} \
if (mt_mask != 0) { \
__asm__ __volatile__("emt; ehb;":::"memory"); \
} \
} \
_ret; \
})
#else
#define KAL_ITC_LOCK_TRY_DI_DMT(lock, irq_mask, mt_mask) \
({ \
kal_status _ret = 0; \
__asm__ __volatile__( \
" .set push;" \
" .set noreorder;" \
" dmt %3;" \
" ehb;" \
" di %2;" \
" ehb;" \
" ext %3, %3, 15, 1;" \
" ext %2, %2, 0, 1;" \
" ll %1, %4;" \
" bnez %1, 1f;" \
" li %1, 0;" \
" li %1, 1;" \
" sc %1, %0;" \
"1: ;" \
" .set pop;" \
: "=ZC" (lock), "+d" (_ret), "+d" (irq_mask), "+d" (mt_mask) \
: "ZC" (lock) \
: "memory" \
); \
if (_ret != 0) { \
_ret = KAL_SUCCESS; \
} else { \
_ret = KAL_ERROR; \
if (irq_mask != 0) { \
__asm__ __volatile__("ei; ehb;":::"memory"); \
} \
if (mt_mask != 0) { \
__asm__ __volatile__("emt; ehb;":::"memory"); \
} \
} \
_ret; \
})
#endif
/* Primitive macro for taking the lock, return only after getting the lock,
* does disable interrupts, disable MT, and raise prio to HW_ITC_GRP.
* Old irq status saved in irq_mask, old MT status saved in mt_mask,
* old prio saved in prio. */
#if defined(__nanomips__)
#define KAL_ITC_LOCK_TAKE_DI_DMT_PRIO(lock, irq_mask, mt_mask, prio) \
({ \
kal_status _ret = 0; \
kal_uint32 _new_prio = KAL_ITC_GRP; \
__asm__ __volatile__( \
" mfc0 %4, $2, 6;" \
" move %1, %4;" \
" ins %1, %6, 2, 2;" \
" ext %4, %4, 2, 2;" \
" dmt %3;" \
" ehb;" \
" mtc0 %1, $2, 6;" \
" ehb;" \
" di %2;" \
" ehb;" \
" ext %3, %3, 15, 1;" \
" ext %2, %2, 0, 1;" \
"1: ll %1, %5;" \
" beqz %1, 4f;" \
" beqz %2, 2f;" \
" ei;" \
" ehb;" \
"2: beqz %3, 3f;" \
" emt;" \
" ehb;" \
"3: pause;" \
" dmt %3;" \
" ehb;" \
" di %2;" \
" ehb;" \
" ext %3, %3, 15, 1;" \
" ext %2, %2, 0, 1;" \
" b 1b;" \
"4: li %1, 1;" \
" sc %1, %0;" \
" beqz %1, 1b;" \
: "=ZC" (lock), "+d" (_ret), "+d" (irq_mask), "+d" (mt_mask), "+d" (prio) \
: "ZC" (lock), "d" (_new_prio) \
: "memory" \
); \
_ret; \
})
#elif defined(__mips16)
#define KAL_ITC_LOCK_TAKE_DI_DMT_PRIO(lock, irq_mask, mt_mask, prio) \
({ \
kal_status _ret = 0; \
kal_uint32 _new_prio = KAL_ITC_GRP; \
__asm__ __volatile__( \
" mfc0 %4, $2, 6;" \
" move %1, %4;" \
" ins %1, %6, 0, 2;" \
" ext %4, %4, 0, 2;" \
" dmt %3;" \
" ehb;" \
" mtc0 %1, $2, 6;" \
" ehb;" \
" di %2;" \
" ehb;" \
" ext %3, %3, 15, 1;" \
" ext %2, %2, 0, 1;" \
"1: ll %1, %5;" \
" beqz %1, 4f;" \
" beqz %2, 2f;" \
" ei;" \
" ehb;" \
"2: beqz %3, 3f;" \
" emt;" \
" ehb;" \
"3: pause;" \
" dmt %3;" \
" ehb;" \
" di %2;" \
" ehb;" \
" ext %3, %3, 15, 1;" \
" ext %2, %2, 0, 1;" \
" b 1b;" \
"4: li %1, 1;" \
" sc %1, %0;" \
" beqz %1, 1b;" \
: "=ZC" (lock), "+d" (_ret), "+d" (irq_mask), "+d" (mt_mask), "+d" (prio) \
: "ZC" (lock), "d" (_new_prio) \
: "memory" \
); \
_ret; \
})
#else
#define KAL_ITC_LOCK_TAKE_DI_DMT_PRIO(lock, irq_mask, mt_mask, prio) \
({ \
kal_status _ret = 0; \
kal_uint32 _new_prio = KAL_ITC_GRP; \
__asm__ __volatile__( \
" .set push;" \
" .set noreorder;" \
" mfc0 %4, $2, 6;" \
" move %1, %4;" \
" ins %1, %6, 0, 2;" \
" ext %4, %4, 0, 2;" \
" dmt %3;" \
" ehb;" \
" mtc0 %1, $2, 6;" \
" ehb;" \
" di %2;" \
" ehb;" \
" ext %3, %3, 15, 1;" \
" ext %2, %2, 0, 1;" \
"1: ll %1, %5;" \
" beqz %1, 4f;" \
" li %1, 1;" \
" beqz %2, 2f;" \
" nop;" \
" ei;" \
" ehb;" \
"2: beqz %2, 3f;" \
" nop;" \
" emt;" \
" ehb;" \
"3: pause;" \
" dmt %3;" \
" ehb;" \
" di %2;" \
" ehb;" \
" ext %3, %3, 15, 1;" \
" ext %2, %2, 0, 1;" \
" b 1b;" \
" nop;" \
"4: sc %1, %0;" \
" beqz %1, 1b;" \
" nop;" \
" .set pop;" \
: "=ZC" (lock), "+d" (_ret), "+d" (irq_mask), "+d" (mt_mask), "+d" (prio) \
: "ZC" (lock), "d" (_new_prio) \
: "memory" \
); \
_ret; \
})
#endif
/* Primitive macro for trying the lock, return success or fail,
* does disable interrupts and MT, and raise prio to HW_ITC_GRP if success.
* Old irq status saved in irq_mask, old MT status saved in mt_mask,
* old prio saved in prio. */
#if defined(__nanomips__)
#define KAL_ITC_LOCK_TRY_DI_DMT_PRIO(lock, irq_maski, mt_mask, prio) \
({ \
kal_status _ret = 0; \
kal_uint32 _new_prio = KAL_ITC_GRP; \
__asm__ __volatile__( \
" mfc0 %4, $2, 6;" \
" move %1, %4;" \
" ins %1, %6, 2, 2;" \
" ext %4, %4, 2, 2;" \
" dmt %3;" \
" ehb;" \
" mtc0 %1, $2, 6;" \
" ehb;" \
" di %2;" \
" ehb;" \
" ext %3, %3, 15, 1;" \
" ext %2, %2, 0, 1;" \
" ll %1, %5;" \
" bnez %1, 1f;" \
" li %1, 1;" \
" sc %1, %0;" \
" b 2f;" \
"1: li %1, 0;" \
"2: ;" \
: "=ZC" (lock), "+d" (_ret), "+d" (irq_mask), "+d" (mt_mask), "+d" (prio) \
: "ZC" (lock), "d" (_new_prio) \
: "memory" \
); \
if (_ret != 0) { \
_ret = KAL_SUCCESS; \
} else { \
_ret = KAL_ERROR; \
if (irq_mask != 0) { \
__asm__ __volatile__("ei; ehb;":::"memory"); \
} \
if (prio != KAL_ITC_GRP) { \
kal_uint32 _tc_schedule = 0; \
__asm__ __volatile__( \
" mfc0 %0, $2, 6;" \
" ins %0, %1, 2, 2;" \
" mtc0 %0, $2, 6;" \
" ehb;" \
: "+d" (_tc_schedule) \
: "d" (prio) \
: \
); \
} \
if (mt_mask != 0) { \
__asm__ __volatile__("emt; ehb;":::"memory"); \
} \
} \
_ret; \
})
#elif defined(__mips16)
#define KAL_ITC_LOCK_TRY_DI_DMT_PRIO(lock, irq_maski, mt_mask, prio) \
({ \
kal_status _ret = 0; \
kal_uint32 _new_prio = KAL_ITC_GRP; \
__asm__ __volatile__( \
" mfc0 %4, $2, 6;" \
" move %1, %4;" \
" ins %1, %6, 0, 2;" \
" ext %4, %4, 0, 2;" \
" dmt %3;" \
" ehb;" \
" mtc0 %1, $2, 6;" \
" ehb;" \
" di %2;" \
" ehb;" \
" ext %3, %3, 15, 1;" \
" ext %2, %2, 0, 1;" \
" ll %1, %5;" \
" bnez %1, 1f;" \
" li %1, 1;" \
" sc %1, %0;" \
" b 2f;" \
"1: li %1, 0;" \
"2: ;" \
: "=ZC" (lock), "+d" (_ret), "+d" (irq_mask), "+d" (mt_mask), "+d" (prio) \
: "ZC" (lock), "d" (_new_prio) \
: "memory" \
); \
if (_ret != 0) { \
_ret = KAL_SUCCESS; \
} else { \
_ret = KAL_ERROR; \
if (irq_mask != 0) { \
__asm__ __volatile__("ei; ehb;":::"memory"); \
} \
if (prio != KAL_ITC_GRP) { \
kal_uint32 _tc_schedule = 0; \
__asm__ __volatile__( \
" mfc0 %0, $2, 6;" \
" ins %0, %1, 0, 2;" \
" mtc0 %0, $2, 6;" \
" ehb;" \
: "+d" (_tc_schedule) \
: "d" (prio) \
: \
); \
} \
if (mt_mask != 0) { \
__asm__ __volatile__("emt; ehb;":::"memory"); \
} \
} \
_ret; \
})
#else
#define KAL_ITC_LOCK_TRY_DI_DMT_PRIO(lock, irq_maski, mt_mask, prio) \
({ \
kal_status _ret = 0; \
kal_uint32 _new_prio = KAL_ITC_GRP; \
__asm__ __volatile__( \
" .set push;" \
" .set noreorder;" \
" mfc0 %4, $2, 6;" \
" move %1, %4;" \
" ins %1, %6, 0, 2;" \
" ext %4, %4, 0, 2;" \
" dmt %3;" \
" ehb;" \
" mtc0 %1, $2, 6;" \
" ehb;" \
" di %2;" \
" ehb;" \
" ext %3, %3, 15, 1;" \
" ext %2, %2, 0, 1;" \
" ll %1, %5;" \
" bnez %1, 1f;" \
" li %1, 0;" \
" li %1, 1;" \
" sc %1, %0;" \
"1: ;" \
" .set pop;" \
: "=ZC" (lock), "+d" (_ret), "+d" (irq_mask), "+d" (mt_mask), "+d" (prio) \
: "ZC" (lock), "d" (_new_prio) \
: "memory" \
); \
if (_ret != 0) { \
_ret = KAL_SUCCESS; \
} else { \
_ret = KAL_ERROR; \
if (irq_mask != 0) { \
__asm__ __volatile__("ei; ehb;":::"memory"); \
} \
if (prio != KAL_ITC_GRP) { \
kal_uint32 _tc_schedule = 0; \
__asm__ __volatile__( \
" mfc0 %0, $2, 6;" \
" ins %0, %1, 0, 2;" \
" mtc0 %0, $2, 6;" \
" ehb;" \
: "+d" (_tc_schedule) \
: "d" (prio) \
: \
); \
} \
if (mt_mask != 0) { \
__asm__ __volatile__("emt; ehb;":::"memory"); \
} \
} \
_ret; \
})
#endif
/* Primitive macro for trying the lock ticket based, return success or fail */
#if defined(__mips16) || defined(__nanomips__)
#define KAL_ITC_LOCK_TRY_FIFO(lock, ticket) \
({ \
kal_status _ret = 0; \
__asm__ __volatile__( \
" ll $a3, %2;" \
" li %0, %3;" \
" bne %1, $a3, 1f;" \
" li %0, %4;" \
"1: ;" \
: "=d"(_ret), "+d"(ticket) \
: "ZC"(lock), "I"(KAL_ERROR), "I"(KAL_SUCCESS) \
: "$a3", "memory"); \
_ret; \
})
#else
#define KAL_ITC_LOCK_TRY_FIFO(lock, ticket) \
({ \
kal_status _ret = 0; \
__asm__ __volatile__( \
" .set push;" \
" .set noreorder;" \
" ll $a3, %2;" \
" bne %1, $a3, 1f;" \
" li %0, %3;" \
" li %0, %4;" \
"1: ;" \
" .set pop;" \
: "=d"(_ret), "+d"(ticket) \
: "ZC"(lock), "I"(KAL_ERROR), "I"(KAL_SUCCESS) \
: "$a3", "memory"); \
_ret; \
})
#endif
/* Primitive macro for releasing the lock */
#if defined(__mips16)
#define KAL_ITC_LOCK_GIVE(lock) \
do { \
__asm__ __volatile__( \
" sync 0x10;" \
" li $a3, 0;" \
" sw $a3, %0;" \
: "=ZC"(lock) \
: \
: "$a3", "memory"); \
} while (0)
#else
#define KAL_ITC_LOCK_GIVE(lock) \
do { \
__asm__ __volatile__( \
" sync 0x10;" \
" sw $zero, %0;" \
: "=ZC"(lock) \
: \
: "memory"); \
} while (0)
#endif
/* Primitive macro for releasing the lock,
* does enable interrupts based on irq_mask*/
#if defined(__mips16)
#define KAL_ITC_LOCK_GIVE_EI(lock, irq_mask) \
do { \
__asm__ __volatile__( \
" sync 0x10;" \
" li $a3, 0;" \
" sw $a3, %0;" \
: "=ZC"(lock) \
: \
: "$a3", "memory"); \
if (irq_mask != 0) { \
__asm__ __volatile__("ei; ehb;" ::: "memory"); \
} \
} while (0)
#else
#define KAL_ITC_LOCK_GIVE_EI(lock, irq_mask) \
do { \
__asm__ __volatile__( \
" sync 0x10;" \
" sw $zero, %0;" \
: "=ZC"(lock) \
: \
: "memory"); \
if (irq_mask != 0) { \
__asm__ __volatile__("ei; ehb;" ::: "memory"); \
} \
} while (0)
#endif
/* Primitive macro for releasing the lock,
* does enable interrupts based on irq_mask, and MT based on mt_mask*/
#if defined(__mips16)
#define KAL_ITC_LOCK_GIVE_EI_EMT(lock, irq_mask, mt_mask) \
do { \
__asm__ __volatile__( \
" sync 0x10;" \
" li $a3, 0;" \
" sw $a3, %0;" \
: "=ZC" (lock) \
: \
: "$a3", "memory" \
); \
if (irq_mask != 0) { \
__asm__ __volatile__("ei; ehb;":::"memory"); \
} \
if (mt_mask != 0) { \
__asm__ __volatile__("emt; ehb;":::"memory"); \
} \
} while(0)
#else
#define KAL_ITC_LOCK_GIVE_EI_EMT(lock, irq_mask, mt_mask) \
do { \
__asm__ __volatile__( \
" sync 0x10;" \
" sw $zero, %0;" \
: "=ZC" (lock) \
: \
: "memory" \
); \
if (irq_mask != 0) { \
__asm__ __volatile__("ei; ehb;":::"memory"); \
} \
if (mt_mask != 0) { \
__asm__ __volatile__("emt; ehb;":::"memory"); \
} \
} while(0)
#endif
/* Primitive macro for releasing the lock,
* does enable interrupts based on irq_mask, MT based on mt_mask, and TC priority based
* on old_prio*/
#if defined(__nanomips__)
#define KAL_ITC_LOCK_GIVE_EI_EMT_PRIO(lock, irq_mask, mt_mask, old_prio) \
do { \
__asm__ __volatile__( \
" sync 0x10;" \
" sw $zero, %0;" \
: "=ZC" (lock) \
: \
: "memory" \
); \
if (irq_mask != 0) { \
__asm__ __volatile__("ei; ehb;":::"memory"); \
} \
if (old_prio != KAL_ITC_GRP) { \
kal_uint32 _tc_schedule = 0; \
__asm__ __volatile__( \
" mfc0 %0, $2, 6;" \
" ins %0, %1, 2, 2;" \
" mtc0 %0, $2, 6;" \
" ehb;" \
: "+d" (_tc_schedule) \
: "d" (old_prio) \
: \
); \
} \
if (mt_mask != 0) { \
__asm__ __volatile__("emt; ehb;":::"memory"); \
} \
} while(0)
#elif defined(__mips16)
#define KAL_ITC_LOCK_GIVE_EI_EMT_PRIO(lock, irq_mask, mt_mask, old_prio) \
do { \
__asm__ __volatile__( \
" sync 0x10;" \
" li $a3, 0;" \
" sw $a3, %0;" \
: "=ZC" (lock) \
: \
: "$a3", "memory" \
); \
if (irq_mask != 0) { \
__asm__ __volatile__("ei; ehb;":::"memory"); \
} \
if (old_prio != KAL_ITC_GRP) { \
kal_uint32 _tc_schedule = 0; \
__asm__ __volatile__( \
" mfc0 %0, $2, 6;" \
" ins %0, %1, 0, 2;" \
" mtc0 %0, $2, 6;" \
" ehb;" \
: "+d" (_tc_schedule) \
: "d" (old_prio) \
: \
); \
} \
if (mt_mask != 0) { \
__asm__ __volatile__("emt; ehb;":::"memory"); \
} \
} while(0)
#else
#define KAL_ITC_LOCK_GIVE_EI_EMT_PRIO(lock, irq_mask, mt_mask, old_prio) \
do { \
__asm__ __volatile__( \
" sync 0x10;" \
" sw $zero, %0;" \
: "=ZC" (lock) \
: \
: "memory" \
); \
if (irq_mask != 0) { \
__asm__ __volatile__("ei; ehb;":::"memory"); \
} \
if (old_prio != KAL_ITC_GRP) { \
kal_uint32 _tc_schedule = 0; \
__asm__ __volatile__( \
" mfc0 %0, $2, 6;" \
" ins %0, %1, 0, 2;" \
" mtc0 %0, $2, 6;" \
" ehb;" \
: "+d" (_tc_schedule) \
: "d" (old_prio) \
: \
); \
} \
if (mt_mask != 0) { \
__asm__ __volatile__("emt; ehb;":::"memory"); \
} \
} while(0)
#endif
/* Primitive macro for releasing the lock ticket based */
#define KAL_ITC_LOCK_GIVE_FIFO(lock) \
do { \
__asm__ __volatile__("sync 0x10;" ::: "memory"); \
(lock)++; \
} while (0)
#define KAL_ITC_PAUSE() \
do { \
__asm__ __volatile__("pause;" ::: "memory"); \
} while (0)
/*******************************************************************************
* Types
*******************************************************************************/
typedef struct kal_itc_node_struct {
struct kal_itc_node_struct *next;
struct kal_itc_node_struct *prev;
} kal_itc_node_s;
typedef struct {
kal_itc_node_s lock_node;
kal_uint32 lock_id;
kal_uint32 lock;
kal_uint32 interrupt_mask;
kal_char name[KAL_ITC_MAX_NAME];
void * owner_context;
kal_uint32 nesting_level;
#if defined(DEBUG_KAL)
kal_uint32 lock_start_time;
kal_uint32 lock_taker;
kal_uint32 max_lock_hold_time;
kal_uint32 max_lock_taker;
#endif
} kal_itc_lock_s;
/*******************************************************************************
* Variables
*******************************************************************************/
extern kal_itc_lock_s *kal_itc_tbl[KAL_ITC_NUM];
extern kal_uint32 kal_tc_prio_count[SYS_MCU_NUM_TC];
extern kal_uint32 kal_tc_prio_save[SYS_MCU_NUM_TC];
#endif //_KAL_ITC_H