/* SPDX-License-Identifier: LGPL-2.1-only OR BSD-3-Clause */
/******************************************************************************
 *
 * This file is provided under a dual license.  When you use or
 * distribute this software, you may choose to be licensed under
 * version 2.1 of the GNU Lesser General Public License
 * ("LGPLv2.1 License") or BSD License.
 *
 * LGPLv2.1 License
 *
 * Copyright(C) 2019 MediaTek Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2.1 of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html for more
 * details.
 *
 * BSD LICENSE
 *
 * Copyright(C) 2019 MediaTek Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *****************************************************************************/


/** @file x_gpio.h
 *  x_gpio.h declare all pinmux/gpio related function and parameters.
 */


#ifndef X_GPIO_H
#define X_GPIO_H

#include "x_typedef.h"
#include "hw_ckgen.h"

//-----------------------------------------------------------------------------
// Configuration
//-----------------------------------------------------------------------------

#ifndef GPIO_THREAD_ENABLE
#define GPIO_THREAD_ENABLE      0
#endif

//-----------------------------------------------------------------------------
// Constant definitions
//-----------------------------------------------------------------------------
#define TOTAL_NORMAL_GPIO_NUM   (NORMAL_GPIO_NUM)
#define NORMAL_GPIO_NUM         200
#define MAX_GPIO_NUM            (409)

#define TOTAL_OPCTRL_NUM        TOTAL_PDWNC_GPIO_NUM

#define TOTAL_GPIO_NUM          (OPCTRL0 + TOTAL_OPCTRL_NUM)//(NORMAL_GPIO_NUM + 8 + TOTAL_OPCTRL_NUM)
#define TOTAL_GPIO_IDX          ((NORMAL_GPIO_NUM + 31) >> 5)
#define GPIO_INDEX_MASK         ((1 << 5) - 1)
#define GPIO_TO_INDEX(gpio)     (((UINT32)(gpio)) >> 5)
#define GPIO_SUPPORT_INT_NUM	96// GPIO0~GPIO95
#define GPIO_EDGE_INTR_NUM      GPIO_SUPPORT_INT_NUM
#define TOTAL_EDGE_IDX          ((GPIO_EDGE_INTR_NUM + 31) >> 5)
#define EDGE_INDEX_MASK         ((1 << 5) - 1)



#define PINMUX0_OFFSET          CKGEN_PMUX0
#define PINMUX1_OFFSET          CKGEN_PMUX1
#define PINMUX2_OFFSET          CKGEN_PMUX2
#define PINMUX3_OFFSET          CKGEN_PMUX3
#define PINMUX4_OFFSET          CKGEN_PMUX4
#define PINMUX5_OFFSET          CKGEN_PMUX5
#define PINMUX6_OFFSET          CKGEN_PMUX6
#define PINMUX7_OFFSET          CKGEN_PMUX7
#define PINMUX8_OFFSET          CKGEN_PMUX8
#define PINMUX_MISC_OFFSET      CKGEN_PMUX_MISC

#define GPIO_OUT0_OFFSET        CKGEN_GPIOOUT0
#define GPIO_EN0_OFFSET         CKGEN_GPIOEN0
#define GPIO_IN0_OFFSET         CKGEN_GPIOIN0
#define GPIO_OUT4_OFFSET        CKGEN_GPIOOUT4
#define GPIO_EN4_OFFSET         CKGEN_GPIOEN4
#define GPIO_IN4_OFFSET         CKGEN_GPIOIN4

#define REG_GPIO_EXTINTEN       CKGEN_EXTINTEN0
#define REG_GPIO_EXTINT         CKGEN_EXTINT0
#define REG_GPIO_ED2INTEN       CKGEN_ED2INTEN0
#define REG_GPIO_LEVINTEN       CKGEN_LEVINTEN0
#define REG_GPIO_ENTPOL         CKGEN_ENTPOL0

#define PINMUX0_WRITE(value)            vIO32Write4B(PINMUX0_OFFSET, (value))
#define PINMUX1_WRITE(value)            vIO32Write4B(PINMUX1_OFFSET, (value))
#define PINMUX2_WRITE(value)            vIO32Write4B(PINMUX2_OFFSET, (value))
#define PINMUX3_WRITE(value)            vIO32Write4B(PINMUX3_OFFSET, (value))
#define PINMUX4_WRITE(value)            vIO32Write4B(PINMUX4_OFFSET, (value))
#define PINMUX5_WRITE(value)            vIO32Write4B(PINMUX5_OFFSET, (value))
#define PINMUX6_WRITE(value)            vIO32Write4B(PINMUX6_OFFSET, (value))
#define PINMUX7_WRITE(value)            vIO32Write4B(PINMUX7_OFFSET, (value))
#define PINMUX8_WRITE(value)            vIO32Write4B(PINMUX8_OFFSET, (value))

#define PINMUX_MISC_WRITE(value)        vIO32Write4B(PINMUX_MISC_OFFSET, (value))
#define PINMUX_WRITE(idx, value)        vIO32Write4B((PINMUX0_OFFSET+(idx << 2)), (value))

#define PINMUX0_REG()                   u4IO32Read4B(PINMUX0_OFFSET)
#define PINMUX1_REG()                   u4IO32Read4B(PINMUX1_OFFSET)
#define PINMUX2_REG()                   u4IO32Read4B(PINMUX2_OFFSET)
#define PINMUX3_REG()                   u4IO32Read4B(PINMUX3_OFFSET)
#define PINMUX4_REG()                   u4IO32Read4B(PINMUX4_OFFSET)
#define PINMUX5_REG()                   u4IO32Read4B(PINMUX5_OFFSET)
#define PINMUX6_REG()                   u4IO32Read4B(PINMUX6_OFFSET)
#define PINMUX7_REG()                   u4IO32Read4B(PINMUX7_OFFSET)
#define PINMUX8_REG()                   u4IO32Read4B(PINMUX8_OFFSET)

#define PINMUX_MISC_REG()               u4IO32Read4B(PINMUX_MISC_OFFSET)
#define PINMUX_REG(idx)                 u4IO32Read4B((PINMUX0_OFFSET+(idx << 2)))


#define GPIO_IN_REG(idx)                u4IO32Read4B(GPIO_IN0_OFFSET+(4*(idx)))
#define GPIO_OUT_REG(idx)               u4IO32Read4B(GPIO_OUT0_OFFSET+(4*(idx)))
#define GPIO_OUT_WRITE(idx,val)         vIO32Write4B((GPIO_OUT0_OFFSET+(4*(idx))), (val))
#define GPIO_EN_REG(idx)                u4IO32Read4B(GPIO_EN0_OFFSET+(4*(idx)))
#define GPIO_EN_WRITE(idx,val)          vIO32Write4B((GPIO_EN0_OFFSET+(4*(idx))), (val))
#define GPIO_ED2INTEN_REG(num)          u4IO32Read4B(REG_GPIO_ED2INTEN + (GPIO_TO_INDEX(num) << 2))
#define GPIO_LEVINTEN_REG(num)          u4IO32Read4B(REG_GPIO_LEVINTEN + (GPIO_TO_INDEX(num) << 2))
#define GPIO_ENTPOL_REG(num)            u4IO32Read4B(REG_GPIO_ENTPOL + (GPIO_TO_INDEX(num) << 2))
#define GPIO_EXTINTEN_REG(num)          u4IO32Read4B(REG_GPIO_EXTINTEN + (GPIO_TO_INDEX(num) << 2))
#define GPIO_RISE_REG(num)			    (~ GPIO_ED2INTEN_REG(num)) & (~ GPIO_LEVINTEN_REG(num))	 & (GPIO_ENTPOL_REG(num)) &  (GPIO_EXTINTEN_REG(num))// 				(~u4IO32Read4B(REG_GPIO_ED2INTEN)) & (~u4IO32Read4B(REG_GPIO_LEVINTEN)) & u4IO32Read4B(REG_GPIO_ENTPOL) & u4IO32Read4B(REG_GPIO_EXTINTEN)
#define GPIO_FALL_REG(num)			    (~ GPIO_ED2INTEN_REG(num)) & (~ GPIO_LEVINTEN_REG(num))	 & (~ GPIO_ENTPOL_REG(num)) &  (GPIO_EXTINTEN_REG(num))						//	(~u4IO32Read4B(REG_GPIO_ED2INTEN)) & (~u4IO32Read4B(REG_GPIO_LEVINTEN)) & (~u4IO32Read4B(REG_GPIO_ENTPOL)) & u4IO32Read4B(REG_GPIO_EXTINTEN)

//-----------------------------------------------------------------------------
// Type definitions
//-----------------------------------------------------------------------------


typedef void (* PFN_GPIO_CALLBACK)(INT32 i4Gpio, BOOL fgStatus);

typedef enum
{
    GPIO_TYPE_NONE = 0,
    GPIO_TYPE_INTR_RISE = 1,        
    GPIO_TYPE_INTR_FALL = 2,
    GPIO_TYPE_INTR_BOTH = 3,
    GPIO_TYPE_INTR_LEVEL_HIGH = 4,    
    GPIO_TYPE_INTR_LEVEL_LOW = 8,
#if GPIO_THREAD_ENABLE
    GPIO_TYPE_POLL_FALL = 9,
    GPIO_TYPE_POLL_RISE = 10,
    GPIO_TYPE_POLL_BOTH = 11,
#endif
    GPIO_TYPE_LAST = 12
} GPIO_TYPE;

typedef struct
{
    INT32 i4Gpio;
    BOOL fgGpioPolarity;
    UINT8 u1LightPeriod;
    UINT8 u1RoundPeriod;
    UINT8 u1Timer;
} GPIO_LED_BLINKER_T;

typedef enum
{
	GPIO_HANDLER_CKGEN = 0,
	GPIO_HANDLER_PDWNC_GPIO,
	GPIO_HANDLER_PDWNC_SRVAD,
} GPIO_HANDLER;

typedef struct
{
	INT32 (*pfnIsOwner)(INT32);    
    INT32 (*pfnInit)(void);	
    INT32 (*pfnEnable)(INT32, INT32*);    
    INT32 (*pfnInput)(INT32);    
    INT32 (*pfnIntrq)(INT32, INT32*);
    INT32 (*pfnOutput)(INT32, INT32*);
    INT32 (*pfnQuery)(INT32 , INT32 *, INT32 *, INT32 *);
    INT32 (*pfnReg)(INT32, GPIO_TYPE, PFN_GPIO_CALLBACK);    
    INT32 (*pfnRegLedBlinker)(INT32, BOOL, UINT8, UINT8);
    INT32 (*pfnStop)(void);
#if defined(CC_FAST_INIT)
	INT32 (*pfnSuspend)(void);	
	INT32 (*pfnResume)(void);    
    INT32 (*pfnResumeIntEn)(INT32, GPIO_TYPE);	
#endif
	INT32 (*pfnSetIntExtParam)(INT32, UINT32 );
    INT32 (*pfnGetIntExtParam)(INT32, UINT32*);
	INT32 (*pfnStatus)(INT32, INT32*, INT32*, INT32*, INT32*);
} GPIO_HANDLER_FUNC_TBL;

//-----------------------------------------------------------------------------
// Public function declaration
//-----------------------------------------------------------------------------

/* GPIO functions. */
EXTERN INT32 GPIO_pm_suspend(void);
EXTERN INT32 GPIO_pm_resume(void);

extern INT32 GPIO_Init(void);
extern INT32 GPIO_Stop(void);

/* Register query/set functions */
EXTERN INT32 GPIO_Output(INT32 i4GpioNum, INT32 *pfgSet);
EXTERN INT32 GPIO_Enable(INT32 i4GpioNum, INT32 *pfgSet);
EXTERN INT32 GPIO_Input(INT32 i4GpioNum);
EXTERN INT32 GPIO_Status(INT32 i4GpioNum, INT32* pi4Pinmux, INT32* pi4Enable, INT32* pi4Output, INT32* pi4Input);
EXTERN INT32 GPIO_Intrq(INT32 i4GpioNum, INT32 *pfgSet);

/* GPIO functions. */
EXTERN INT32 GPIO_Query(INT32 i4Gpio, INT32 *pi4Intr, INT32 *pi4Fall, INT32 *pi4Rise);
EXTERN INT32 GPIO_Reg(INT32 i4Gpio, GPIO_TYPE eType, PFN_GPIO_CALLBACK pfnCallback);
EXTERN INT32 GPIO_SetOut(INT32 i4GpioNum, INT32 i4Val);
EXTERN INT32 GPIO_GetIn(INT32 i4GpioNum);
EXTERN INT32 GPIO_INTEN(INT32 i4Gpio, GPIO_TYPE eType);
EXTERN INT32 GPIO_RegPeriodLevel(INT32 i4Gpio, INT32 i4HighLow, UINT32 u4Period/*mili-second*/, PFN_GPIO_CALLBACK pfnCallback);
EXTERN INT32 GPIO_SetIntExtParam(INT32 i4Gpio, UINT32 u4Arg);
EXTERN INT32 GPIO_GetIntExtParam(INT32 i4Gpio, UINT32 *pu4Arg);

#endif //X_GPIO_H
