/*
 *
 * Copyright (C) 2012-2021, Samsung Electronics Co., Ltd.
 *
 * GPIO interface, local implementation
 */

#include <errno.h>
#include "dbg.h"
#include "device.h"
#include "secmap.h"
#include <tee_smc.h>
#include "touch_gpio.h"

#ifdef USE_TOUCH_INTERRUPT

/* DEINT */
#define MTK_SIP_TEE_SEC_DEINT_CONFIGURE_AARCH32     0x8200020C
#define MTK_SIP_TEE_SEC_DEINT_CONFIGURE_AARCH64     0xC200020C
#define MTK_SIP_TEE_SEC_DEINT_RELEASE_AARCH32       0x8200020D
#define MTK_SIP_TEE_SEC_DEINT_RELEASE_AARCH64       0xC200020D
#define MTK_SIP_TEE_SEC_DEINT_ACK_AARCH32           0x8200020E
#define MTK_SIP_TEE_SEC_DEINT_ACK_AARCH64           0xC200020E
#define MTK_SIP_TEE_SEC_DEINT_MASK_AARCH32          0x8200020F
#define MTK_SIP_TEE_SEC_DEINT_MASK_AARCH64          0xC200020F

static void gpio_save_state(void)
{
    int smc_ret;
    TEE_Result res;
    TEES_SMCHandle handle;
    TEES_SMCData data = {
        .arg_types = SMC_ARG_TYPES(SMC_ARG_TYPE_VALUE,
        SMC_ARG_TYPE_VALUE,
        SMC_ARG_TYPE_VALUE,
        0, 0, 0, 0),
        .args.args[0] = MTK_SIP_TEE_SEC_DEINT_CONFIGURE_AARCH32,
        .args.args[1] = TSP_INT,
        .args.args[2] = TOUCH_INT_NUM,
        .args.args[3] = EINTF_TRIGGER_LEVEL_LOW,
    };

    res = TEES_SMCInit(&handle);
    if (res != TEE_SUCCESS) {
        errPrintf("%s Failed to initialize SMC, tee_err: %x\n", __func__, res);
        TEE_Panic(1);
    }

    res = TEES_SMCCommand(handle, &data);
    if (res != TEE_SUCCESS) {
        errPrintf("%s Failed to call SMC, tee_err: %x\n", __func__, res);
        TEES_SMCFini(handle);
        TEE_Panic(1);
    }

    /* Return 0 in case of success SMC call */
    res = TEES_SMCFini(handle);
    smc_ret = data.args.args[0];
    if (res != TEE_SUCCESS || smc_ret != 1) {
        errPrintf("%s smc call failed, smc_ret:0x%x, res:%d!\n", __func__, smc_ret, res);
        TEE_Panic(1);
    }

    dbgPrintf("%s smc call success for EINT, res:0x%x!\n", __func__, smc_ret);
}

int map_gpio_sfr(void)
{
    return 0;
}

void gpio_restore_state(void)
{
    int smc_ret;
    TEE_Result res;
    TEES_SMCHandle handle;
    TEES_SMCData data = {
        .arg_types = SMC_ARG_TYPES(SMC_ARG_TYPE_VALUE,
        SMC_ARG_TYPE_VALUE,
        0, 0, 0, 0, 0),
        .args.args[0] = MTK_SIP_TEE_SEC_DEINT_RELEASE_AARCH32,
        .args.args[1] = TOUCH_INT_NUM,
    };

    res = TEES_SMCInit(&handle);
    if (res != TEE_SUCCESS) {
        errPrintf("%s Failed to initialize SMC, tee_err: %x\n", __func__, res);
        TEE_Panic(1);
    }

    res = TEES_SMCCommand(handle, &data);
    if (res != TEE_SUCCESS) {
        errPrintf("%s Failed to call SMC, tee_err: %x\n", __func__, res);
        TEES_SMCFini(handle);
        TEE_Panic(1);
    }

    /* Return 0 in case of success SMC call */
    res = TEES_SMCFini(handle);
    smc_ret = data.args.args[0];
    if (res != TEE_SUCCESS || smc_ret) {
        errPrintf("%s smc call failed, smc_ret:0x%x, res:%d!\n", __func__, smc_ret, res);
        TEE_Panic(1);
    }

    dbgPrintf("%s smc call success for EINT, res:0x%x!\n", __func__, smc_ret);
}

void gpio_config(void)
{
    gpio_save_state();
}

/* Enable/disable touch attention interrupt from gpio */
void gpio_enable_touch_irq(bool enable)
{
    TEE_Result res;
    TEES_SMCHandle handle;
    int smc_ret, mask;

    if (enable)
        mask = 0x1;  //unmask
    else
        mask = 0x0;  //mask

    TEES_SMCData data = {
        .arg_types = SMC_ARG_TYPES(SMC_ARG_TYPE_VALUE,
        SMC_ARG_TYPE_VALUE,
        0, 0, 0, 0, 0),
        .args.args[0] = MTK_SIP_TEE_SEC_DEINT_MASK_AARCH32,
        .args.args[1] = TSP_INT,
        .args.args[2] = mask,
    };

    res = TEES_SMCInit(&handle);
    if (res != TEE_SUCCESS) {
        errPrintf("%s Failed to initialize SMC, tee_err: %x\n", __func__, res);
        TEE_Panic(1);
    }

    res = TEES_SMCCommand(handle, &data);
    if (res != TEE_SUCCESS) {
        errPrintf("%s Failed to call SMC, tee_err: %x\n", __func__, res);
        TEES_SMCFini(handle);
        TEE_Panic(1);
    }

    /* Return 0 in case of success SMC call */
    res = TEES_SMCFini(handle);
    smc_ret = data.args.args[0];
    if (res != TEE_SUCCESS || smc_ret) {
        errPrintf("%s smc call failed, smc_ret:0x%x, res:%d!\n", __func__, smc_ret, res);
        TEE_Panic(1);
    }

    dbgPrintf("%s smc call success for EINT MASK(0x%x), res:0x%x!\n", __func__, mask, smc_ret);
}

/* Clear pending touch attention interrupt */
void gpio_clear_pend_irq(void)
{
    int smc_ret;
    TEE_Result res;
    TEES_SMCHandle handle;
    TEES_SMCData data = {
        .arg_types = SMC_ARG_TYPES(SMC_ARG_TYPE_VALUE,
        SMC_ARG_TYPE_VALUE,
        0, 0, 0, 0, 0),
        .args.args[0] = MTK_SIP_TEE_SEC_DEINT_ACK_AARCH32,
        .args.args[1] = TSP_INT,
    };

    res = TEES_SMCInit(&handle);
    if (res != TEE_SUCCESS) {
        errPrintf("%s Failed to initialize SMC, tee_err: %x\n", __func__, res);
        TEE_Panic(1);
    }

    res = TEES_SMCCommand(handle, &data);
    if (res != TEE_SUCCESS) {
        errPrintf("%s Failed to call SMC, tee_err: %x\n", __func__, res);
        TEES_SMCFini(handle);
        TEE_Panic(1);
    }

    /* Return 0 in case of success SMC call */
    res = TEES_SMCFini(handle);
    smc_ret = data.args.args[0];
    if (res != TEE_SUCCESS || smc_ret) {
        errPrintf("%s smc call failed, smc_ret:0x%x, res:%d!\n", __func__, smc_ret, res);
        TEE_Panic(1);
    }

    dbgPrintf("%s smc call success for EINT, res:0x%x!\n", __func__, smc_ret);
}
#endif /* USE_TOUCH_INTERRUPT */
