| /***************************************************************************** |
| * 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 |