/* Copyright Statement:
 *
 * This software/firmware and related documentation ("MediaTek Software") are
 * protected under relevant copyright laws. The information contained herein is
 * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
 * the prior written permission of MediaTek inc. and/or its licensors, any
 * reproduction, modification, use or disclosure of MediaTek Software, and
 * information contained herein, in whole or in part, shall be strictly
 * prohibited.
 *
 * Copyright  (C) [2020]  MediaTek Inc. All rights reserved.
 *
 * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
 * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
 * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
 * 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 RECEIVER AGREES
 * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
 * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
 * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
 * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
 * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
 * STANDARD OR OPEN FORUM. RECEIVER'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 RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
 *
 * The following software/firmware and/or related documentation ("MediaTek
 * Software") have been modified by MediaTek Inc. All revisions are subject to
 * any receiver's applicable license agreements with MediaTek Inc.
 */

#ifndef _MTK_DEBUG_HEADER_
#define _MTK_DEBUG_HEADER_

#define EBUSY 16
#define STR_ERROR "ERROR"
#define STR_INFO "INFO"
#define STR_TRACE "TRACE"
#define STR_DEBUG "DEBUG"
#define STR_BOOTTIME "BOOTTIME"
#define STR_UDTBDEBUG "UDTB"
#define STR_KDTBDEBUG "KDTB"
#define STR_DISABLE "DISABLE"

typedef enum
{
    EN_DEBUG_LEVEL_DISABLE=0,
    EN_DEBUG_LEVEL_ERROR=0x01,
    EN_DEBUG_LEVEL_INFO=0x02,
    EN_DEBUG_LEVEL_TRACE=0x04,
    EN_DEBUG_LEVEL_DEBUG=0x08,
    EN_DEBUG_LEVEL_BOOTTIME=0x10,
    EN_DEBUG_LEVEL_UDTBDEBUG=0x20,
    EN_DEBUG_LEVEL_KDTBDEBUG=0x40,
    EN_DEBUG_LEVEL_INVALID=0x1000,
    EN_DEBUG_LEVEL_MAX=EN_DEBUG_LEVEL_INVALID
}EN_DEBUG_LEVEL;

typedef enum
{
    EN_DEBUG_MODULE_DISABLE=0,
    EN_DEBUG_MODULE_UPGRADE=(0x01<<0),
    EN_DEBUG_MODULE_FAT=(0x01<<1),
    EN_DEBUG_MODULE_ALL=0xFFFFFFFF
}EN_DEBUG_MODULE;

#define ENV_DEBUG_LEVLE "dbgLevel"

extern EN_DEBUG_LEVEL dbgLevel;
extern EN_DEBUG_MODULE dbgModule;

#define DEFAULT_DEBUG_LEVEL (EN_DEBUG_LEVEL_ERROR)
#define DEFAULT_DEBUG_MODULE (EN_DEBUG_MODULE_ALL)

#if defined(CONFIG_MULTICORES_PLATFORM)
#include <smp/thread_info.h>

#define UBOOT_ERROR(msg, ...) \
    do { \
        if (dbgLevel & EN_DEBUG_LEVEL_ERROR) \
        { \
            printf("\033[0;31m[ERROR][cpu:%d] %s:%d: \033[0m" msg, get_cpu_id(), __FUNCTION__, __LINE__, ##__VA_ARGS__); \
        } \
    } while (0)

#define UBOOT_INFO(msg, ...) \
    do { \
        if (dbgLevel & EN_DEBUG_LEVEL_INFO) \
        { \
            printf("[cpu:%d] " msg, get_cpu_id(), ##__VA_ARGS__); \
        } \
    } while (0)

#define UBOOT_BOOTTIME(msg, ...) \
    do { \
        if (dbgLevel & EN_DEBUG_LEVEL_BOOTTIME) \
        { \
            printf("[cpu:%d] " msg, get_cpu_id(), ##__VA_ARGS__); \
        } \
    } while (0)

#define UBOOT_TRACE(msg, ...) \
    do { \
        if (dbgLevel & EN_DEBUG_LEVEL_TRACE) \
        { \
            printf("\033[0;32m[TRACE][cpu:%d] %s \033[0m" msg, get_cpu_id(), __FUNCTION__, ##__VA_ARGS__); \
        } \
    } while (0)

#define UBOOT_DEBUG(msg, ...) \
    do { \
        if (dbgLevel & EN_DEBUG_LEVEL_DEBUG) \
        { \
            printf("\033[0;34m[DEBUG][cpu:%d] %s:%d: \033[0m" msg, get_cpu_id(), __FUNCTION__, __LINE__, ##__VA_ARGS__); \
        } \
    } while (0)

#define UBOOT_DUMP(addr, size) \
    do { \
        if (dbgLevel & EN_DEBUG_LEVEL_DEBUG) \
        { \
            printf("\033[0;34m[DUMP][cpu:%d] %s:%d:\033[0m\n", get_cpu_id(), __FUNCTION__, __LINE__); \
            _dump((void *)addr, size); \
        } \
    } while (0)

#define UBOOT_ERRDUMP(addr, size) \
    do { \
        if (dbgLevel & EN_DEBUG_LEVEL_ERROR) \
        { \
            printf("\033[0;31m[DUMP][cpu:%d] %s:%d:\033[0m\n", get_cpu_id(), __FUNCTION__, __LINE__); \
            _dump((void *)addr, size); \
        } \
    } while (0)

#else
#define UBOOT_ERROR(msg, ...) \
    do { \
        if (dbgLevel & EN_DEBUG_LEVEL_ERROR) \
        { \
            printf("\033[0;31m[ERROR] %s:%d: \033[0m" msg, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
        } \
    } while (0)

#define UBOOT_INFO(msg...) \
    do { \
        if (dbgLevel & EN_DEBUG_LEVEL_INFO) \
        { \
            printf(msg); \
        } \
    } while (0)

#define UBOOT_BOOTTIME(msg...) \
    do { \
        if (dbgLevel & EN_DEBUG_LEVEL_BOOTTIME) \
        { \
            printf(msg); \
        } \
    } while (0)

#define UBOOT_TRACE(msg, ...) \
    do { \
        if (dbgLevel & EN_DEBUG_LEVEL_TRACE) \
        { \
            printf("\033[0;32m[TRACE] %s \033[0m" msg, __FUNCTION__, ##__VA_ARGS__); \
        } \
    } while (0)

#define UBOOT_DEBUG(msg, ...) \
    do { \
        if (dbgLevel & EN_DEBUG_LEVEL_DEBUG) \
        { \
            printf("\033[0;34m[DEBUG] %s:%d: \033[0m" msg, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
        } \
    } while (0)

#define UBOOT_DUMP(addr, size) \
    do { \
        if (dbgLevel & EN_DEBUG_LEVEL_DEBUG) \
        { \
            printf("\033[0;34m[DUMP] %s:%d:\033[0m\n", __FUNCTION__, __LINE__); \
            _dump((void *)addr, size); \
        } \
    } while (0)

#define UBOOT_ERRDUMP(addr, size) \
    do { \
        if (dbgLevel & EN_DEBUG_LEVEL_ERROR) \
        { \
            printf("\033[0;31m[DUMP] %s:%d:\033[0m\n", __FUNCTION__, __LINE__); \
            _dump((void *)addr, size); \
        } \
    } while (0)
#endif

void backtrace(void);
int _init_debug_level(void);
void debug_dtb(unsigned long address, char *option);
void _dump(void *addr, unsigned int size);
#endif
