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


#ifndef X_CKGEN_H
#define X_CKGEN_H

#include "x_hal_5381.h"
#include "hw_ckgen.h"


#define CKGENHW_DEBUG   0

//===========================================================================
// Macros for register read/write

#define CKGEN_READ8(offset)             IO_READ8(CKGEN_BASE, (offset))
#define CKGEN_READ16(offset)            IO_READ16(CKGEN_BASE, (offset))
// #define CKGEN_READ32(offset)         IO_READ32(CKGEN_BASE, (offset))

#define CKGEN_WRITE8(offset, value)     IO_WRITE8(CKGEN_BASE, (offset), (value))
#define CKGEN_WRITE16(offset, value)    IO_WRITE16(CKGEN_BASE, (offset), (value))
// #define CKGEN_WRITE32(offset, value) IO_WRITE32(CKGEN_BASE, (offset), (value))

#define CKGEN_REG8(offset)              IO_REG8(CKGEN_BASE, (offset))
#define CKGEN_REG16(offset)             IO_REG16(CKGEN_BASE, (offset))
#define CKGEN_REG32(offset)             IO_REG32(CKGEN_BASE, (offset))

#if CKGENHW_DEBUG

// implement at ckgen.c
EXTERN void CKGENDB_IoWr(UINT32 u4Offset, UINT32 u4Value, INT8 *szFile, INT32 Line);
EXTERN UINT32 CKGENDB_IoRd(UINT32 u4Offset, INT8 *szFile, INT32 Line);

#define CKGEN_WRITE32(offset, value)      CKGENDB_IoWr(offset, value, __FILE__, __LINE__)
#define CKGEN_READ32(offset)              CKGENDB_IoRd(offset, __FILE__, __LINE__)

#else /* CKGENHW_DEBUG */

#define CKGEN_WRITE32(offset, value)      IO_WRITE32(CKGEN_BASE, (offset), (value))
#define CKGEN_READ32(offset)              IO_READ32(CKGEN_BASE, (offset))

#endif /* CKGENHW_DEBUG */


//----------------------------------------------------------------------------
// PLL Register definitions
//----------------------------------------------------------------------------
//add by david.hsieh 20090504

#define REG_PINMUX_SEL0         (0x0400)    // Pin function multiplexer selection 0
#define REG_PINMUX_SEL1         (0x0404)    // Pin function multiplexer selection 1
#define REG_PINMUX_SEL2         (0x0408)    // Pin function multiplexer selection 2
#define REG_PINMUX_SEL3         (0x040c)    // Pin function multiplexer selection 3
#define REG_PINMUX_MISC         (0x0410)    // Pin function multiplexer misc

//add by david.hsieh 20090504
//----------------------------------------------------------------------------
// XTAL config
EXTERN BOOL BSP_IsFPGA(void);

#define XTAL_STRAP_MODE (IO32ReadFldAlign(CKGEN_STRAP_OP, FLD_STRAP_0) & 0x4)
    #define SET_XTAL_24MHZ  (0)
    #define SET_XTAL_27MHZ  (8)
    #define SET_XTAL_54MHZ  (2)
    #define IS_XTAL_54MHZ() (0)
    #define IS_XTAL_60MHZ() (0)
    #define IS_XTAL_24MHZ() (1)
    #define IS_XTAL_27MHZ() (0)
    #define IS_XTAL_30MHZ() (0)
    #define GET_XTAL_CLK()  (CLK_24MHZ)

//=====================================================================
// Constant definitions Given by ACD analog designer
#define PLL_BAND_NUM           8


//----------------------------------------------------------------------------
// clock const definitions
#define CLK_13_5MHZ             13500000    // 13.5 MHz
#define CLK_20MHZ               20000000    // 20 MHz
#define CLK_24MHZ               24000000    // 24 MHz
#define CLK_27MHZ               27000000    // 27 MHz
#define CLK_30MHZ               30000000    // 30 MHz
#define CLK_40MHZ               40000000    // 40 MHz
#define CLK_50MHZ               50000000    // 50 MHz
#define CLK_54MHZ               54000000    // 54 MHz
#define CLK_60MHZ               60000000    // 60 MHz
#define CLK_81MHZ               81000000    // 81 MHz
#define CLK_100MHZ              100000000   // 100 MHz
#define CLK_120MHZ              120000000   // 120 MHz
#define CLK_231_43MHZ           231430000   // 231.43 MHz
#define CLK_243MHZ              243000000   // 243 MHz
#define CLK_246_86MHZ           246860000   // 246.86 MHz
#define CLK_259_2MHZ            259200000   // 259.2 MHz
#define CLK_324MHZ              324000000   // 324 MHz
#define CLK_337_5MHZ            337500000   // 337.5 MHz
#define CLK_351MHZ              351000000   // 351 MHz
#define CLK_405MHZ              405000000   // 405 MHz
#define CLK_432MHZ              432000000   // 432 MHz
#define CLK_APLL147MHz          147000000   // 147 MHz
#define CLK_APLL294MHZ          294912000   // 294.912 MHz
#define CLK_APLL270MHZ          270950400   // 270.9404 MHz
#define CLK_200MHZ              200000000
#define CLK_250MHZ              250000000
#define CLK_300MHZ              300000000
#define CLK_400MHZ              400000000
#define CLK_500MHZ              500000000
#define CLK_550MHZ              550000000
#define CLK_600MHZ              600000000



//===========================================================================
// PLL default clock settings

#define APLL1_DEFAULT_CLOCK     CLK_APLL294MHZ  // 270.9504M
#define VPLL_DEFAULT_CLOCK      CLK_81MHZ   // 81 MHz
#define APLL2_DEFAULT_CLOCK     CLK_APLL270MHZ  // 294.912M

//=====================================================================
// Type definitions

typedef enum
{
    CAL_SRC_SAWLESSPLL = 0,             // 0
    CAL_SRC_CPUPLL_D2,                  // 1
    CAL_SRC_SYSPLL_D2,                  // 2
    CAL_SRC_APLL1,                      // 3
    CAL_SRC_DMPLL_VCO,                   // 4
    CAL_SRC_APLL2,                      // 5
    CAL_SRC_APLL2_D3,                   // 6
    CAL_SRC_ADCPLL,                     // 7
    CAL_SRC_M_CK,                       // 8
    CAL_SRC_G3DPLL,                     // 9        VDECPLL
    CAL_SRC_FBOUT,                      // 0x0A
    CAL_SRC_USBPLL,                     // 0x0B
    CAL_SRC_DDR_2CH_4,              // 0x0C
    CAL_SRC_ETHPLL_D2,                  // 0x0D
    CAL_SRC_XTAL,                       // 0x0E
    CAL_SRC_ADC_CKTOUT,                 // 0x0F

	CAL_SRC_VDECSOCPLL_CK456M,			// 0X10
    CAL_SRC_PCLKPIN,       // 0x11
    CAL_SRC_PDTCLKPIN,                  // 0x12
    CAL_SRC_HDMI_DEEP250,       // 0x13
    CAL_SRC_DDDS1_VSP,                  // 0x14
    CAL_SRC_DDDS2_VSP,                  // 0x15
    CAL_SRC_VPLL_TCON_CK,               // 0x16
    CAL_SRC_LVDS_DPIX_CK,               // 0x17
    CAL_SRC_PIXPLL,                     // 0x18
    CAL_SRC_CLKDIG_CTS_D11,             // 0x19
    CAL_SRC_TCLK,                       // 0x1A
    CAL_SRC_OCLK,                       // 0x1B
    CAL_SRC_LVDS_CLK_CTS,               // 0x1C
    CAL_SRC_HDMI_0_CH1_340M_CK,         // 0x1D
    CAL_SRC_VDECPLL_CK588M,             // 0x1E
    CAL_SRC_TVD_CLK = 0x1F,     		// 0x1F

    CAL_SRC_DMDDS_MONCLK,               // 0x20
    CAL_SRC_ETHER_PHY,                    // 0x21
    CAL_SRC_VENC_MON_3,                // 0x22
    CAL_SRC_VENC_MON_2,          // 0x23
    CAL_SRC_SPL_2CORE,         // 0x24
    CAL_SRC_DMAD_I_CLK_CTS,         // 0x25
    CAL_SRC_HDMI_2_MON_CK2,         // 0x26
    CAL_SRC_HDMI_3_CH2_CK_EQ,          // 0x27
    CAL_SRC_HDMI_3_CHCK_CK_EQ,          // 0x28
    CAL_SRC_HDMI_1_DEEPCLRCLK,         // 0x29
    CAL_SRC_HDMI_2_DEEPCLRCLK,          // 0x2A
    CAL_SRC_HDMI_3_DEEPCLRCLK,          // 0x2B
    CAL_SRC_HDMI_2_CH0_CK_EQ,         // 0x2C
    CAL_SRC_HDMI_2_CH1_CK_EQ,          // 0x2D
    CAL_SRC_XPLL_CK600M,          // 0x2E
    CAL_SRC_LVDSA_MONCLK,         // 0x2F
    CAL_SRC_EARC_CM_SLEW_CK,         // 0x30

    CAL_SRC_CLK_DIG_D11,// 0x31
    CAL_SRC_VOPLL_TEST_CK, // 0x32
    CAL_SRC_SYNC_CK,                 // 0x33
    CAL_SRC_SYNC2_CK,              // 0x34
    CAL_SRC_HDMI_2_CH2_CK_EQ,                  // 0x35
    CAL_SRC_HDMI_2_CHCK_CK_EQ,                  // 0x36
    CAL_SRC_HDMI_3_MON_CK2,         // 0x37
    CAL_SRC_DDR_2CH_1,         // 0x38
    CAL_SRC_VDEC_SYS_CK,         // 0x39
    CAL_SRC_HDMI_3_CH0_CK,         // 0x3A
    CAL_SRC_EARC_TX_PLL,         // 0x3B
    CAL_SRC_DMUXBACKPLL,       // 0x3C
    CAL_SRC_MJCPLL,                 // 0x3D
    CAL_SRC_CKT_B,                // 0x3E
    CAL_SRC_CKT_A,                // 0x3F

    CAL_SRC_USB20_MONCLK_3P,                      // 0x40
    CAL_SRC_USB20_MONCLK_2P,                      // 0x41
    CAL_SRC_USB20_MONCLK_1P,            // 0x42
    CAL_SRC_USB20_MONCLK_0P,            // 0x43
    CAL_SRC_DDR_2CH_0,               // 0x44
    CAL_SRC_DDR_2CH_7,       // 0x45
    CAL_SRC_DDR_8,       // 0x46
    CAL_SRC_DMUXPLL_CK396M,                // 0x47
	CAL_SRC_DDR_2,			// 0x48
	CAL_SRC_DDR_5,			// 0x49
    CAL_SRC_DDR_6,                // 0x4A
    CAL_SRC_DDR_2CH_5,         // 0x4B
    CAL_SRC_DDR_2CH_8,               // 0x4C
    CAL_SRC_ARMPLL_CK1250M,             // 0x4D
    CAL_SRC_HPCPLL_MONCLK,              // 0x4E
    CAL_SRC_DDDS2_MONCLK,               // 0x4F

    CAL_SRC_XDDS_MONCLK = 0x50,         // 0x50
    CAL_SRC_DDDS1_MONCLK,               // 0x51
    CAL_SRC_HADDS1_MONCLK,              // 0x52
    CAL_SRC_VDECPLL_CK588M_2,             // 0x53
    CAL_SRC_SYSPLL_CK648M,              // 0x54
    CAL_SRC_CCIPLL_MONCLK,             // 0x55
    CAL_SRC_G3DPLL_2,              // 0x56
    CAL_SRC_PLLGP_MONCLK,               // 0x57
    CAL_SRC_EARC_TX_PLL_CK491P52M,                // 0x58
    CAL_SRC_MON_TCLK_DIV,               // 0x59
    CAL_SRC_MON_OCLK_DIV2,              // 0x5A
    CAL_SRC_MON_OCLK_DIV,               // 0x5B
    CAL_SRC_MON_CLK75M_CK,              // 0x5C
    CAL_SRC_DDDS2_CK,                   // 0x5D
    CAL_SRC_VDECSOCPLL_CK456,                    // 0x5E
    CAL_SRC_MAIN2_H,                  // 0x5F
	
    CAL_SRC_BLK2RS_HS,               // 0x60
    CAL_SRC_MIB_OUT_M_HS,             // 0x61
    CAL_SRC_DDR_1,             // 0x62
    CAL_SRC_DDR_0,                // 0x63
    CAL_SRC_PCIE_REF_CK,         // 0x64
    CAL_SRC_HDMI_3_CH1_CK_EQ,              // 0x65
    CAL_SRC_APLL3_MONCLK,              // 0x66
    CAL_SRC_HADDS2_MONCLK,             // 0x67
    CAL_SRC_IP_MON_3,         // 0x68
    CAL_SRC_EARC_DM_SLEW_CK,             // 0x69
    CAL_SRC_HADDS2_REFCLK_216M,         // 0x6A
	CAL_SRC_HDMI_1_MON_CK2,     		// 0x6B
	CAL_SRC_HDMI_0_MON_CK2, 	    // 0x6C
	CAL_SRC_DDR_9, 		// 0x6D
	CAL_SRC_DDR_4, 		// 0x6E
    CAL_SRC_DDR_2CH_6,            // 0x6F
    
    CAL_SRC_DDR_3,       // 0x70
    CAL_SRC_AD_SOGY_OUT_MON,            // 0x71
    CAL_SRC_AD_SOGY_OUT,                // 0x72
    CAL_SRC_AD_VSYNC_OUT,               // 0x73
    CAL_SRC_AD_HSYNC_OUT,               // 0x74
    CAL_SRC_AD_FB_OUT,                  // 0x75
    CAL_SRC_DDR_2CH_2,  // 0x76
    CAL_SRC_DDR_2CH_3,         // 0x77
    CAL_SRC_DDR_7,             // 0x78
    CAL_SRC_DDR_2CH_9,         // 0x79
    
    CAL_SRC_AD_HDMI_3_MON_CK,           // 0x7A
    CAL_SRC_AD_HDMI_2_MON_CK,           // 0x7B
    CAL_SRC_AD_HDMI_1_MON_CK,           // 0x7C
    CAL_SRC_AD_HDMI_0_MON_CK,           // 0x7D
    CAL_SRC_AD_HPCPLL_MON_CK,          // 0x7E
    CAL_SRC_AD_ETH_TANA_CLK250,           // 0x7F
    
    SRC_CPU_CLK = 128,                  // 0x80
    SRC_MEM_CLK,                        // 0x81
    SRC_BUS_CLK,                        // 0x82
    SRC_TIMER_CLK,                      // 0x83
    SRC_SYSPLL_CLK,                     // 0x84
    SRC_APLL1_CLK,                      // 0x85
    SRC_APLL2_CLK,                      // 0x86
    SRC_SAWLESSPLL_CLK,                 // 0x87
    SRC_ADCPLL_CLK,                     // 0x88
    SRC_ETHPLL_CLK,                     // 0x89
    SRC_VDECPLL_CLK,                    // 0x8A
    SRC_XPLL_CLK,                       // 0x8B
    SRC_VOPLL_CLK,                      // 0x8C
    SRC_G3DPLL_CLK,                     // 0x8D
    SRC_DMUXPLL_CLK,                    // 0x8E
	SRC_ETHNETPLL_CLK,					// 0x8F

    SRC_POCLK = 144,                    // 0x90
    SRC_VDOIN_MPCLK,                    // 0x91
    SRC_MIB_OCLK,                       // 0x92
    SRC_POCLK_DPLL,                     // 0x93

    SRC_MJC_CLK = 160,                  // 0xA0
    SRC_SMI_CLK,                        // 0xA1
    SRC_SMI_BUS_CLK,                    // 0xA2

    SRC_LEVEL_1_CK_OUT = 0x10000,
    CAL_SRC_MCUSYS_ARM_CLK = 0x10001,
    CAL_SRC_MP2_ARM_JIT = 0x10002,
    CAL_SRC_TCLK2 = 0x10003,
    CAL_SRC_MJCPLL_2 = 0x10004,
    CAL_SRC_HPCPLL_CK1000M = 0x10005,
    CAL_SRC_EARC_CK_MON = 0x10006,
    CAL_SRC_EARCTXPLL_CK = 0x10007,
    CAL_SRC_BUS_ARM_JIT = 0x10008,
    CAL_SRC_MCUSYS_ARM = 0x10009,
    CAL_SRC_APUPLL = 0x1000A,
    CAL_SRC_CILINKPLL = 0x1000B,
    CAL_SRC_DMUX_STC_DDS = 0x1000C,
    CAL_SRC_EARCTXPLL = 0x1000D,
    CAL_SRC_ENGPLL = 0x1000E,
    CAL_SRC_AUD4_SRC = 0x1000F,

    CAL_SRC_APLL3 = 0x10010,
    CAL_SRC_XPLL_CK25M = 0x10011,
    CAL_SRC_XPLL_CK480M = 0x10012,
    CAL_SRC_TMDSPLL1 = 0x10013,
    CAL_SRC_TMDSPLL2 = 0x10014,
    CAL_SRC_HADDS2 = 0x10015,
    CAL_SRC_DMDDS = 0x10016,
    CAL_SRC_DMUX_STC_DDS_MONCLK = 0x10017,
    CAL_SRC_DMUX_STC_DDS_VSP = 0x10018,
    CAL_SRC_XDDS_CLK = 0x10019,
    CAL_SRC_CLKO_DMPLL_VCO_DIV4 = 0x1001A,
    CAL_SRC_EARCTXPLL_DIV6 = 0x1001B,
    CAL_SRC_VPLL_TCON2 = 0x1001C,
    CAL_SRC_ARMPLL_MON_CK = 0x1001D,
    CAL_SRC_G3DPLL_MON_CK = 0x1001E,
    CAL_SRC_CCIPLL_VPROC = 0x1001F,

    SRC_UNKNOWN
} CAL_SRC_T;

//=====================================================================
// Interface

#define BSP_GetDomainClock(eSrc)    BSP_GetClock(eSrc, NULL, NULL, NULL, NULL)
#define BSP_GetPLLClock(eSrc)       BSP_GetClock(eSrc, NULL, NULL, NULL, NULL)

extern void BSP_CkgenInit(void);

extern BOOL BSP_Calibrate(CAL_SRC_T eSource, UINT32 u4Clock);

extern UINT32 BSP_GetClock(CAL_SRC_T eSrc, UINT8* pu1Band, UINT16* pu2MS,
    UINT16* pu2NS, UINT16* pu2Counter);

extern void vDrvVOPLLFreqSet(UINT32 u4CLK);
extern void vDrvVOPLLSet(void);
extern UINT32 _CalGetPLLCounter(UINT32 u4CalSel);

extern UINT32 BSP_GetBand(CAL_SRC_T ePll);
extern UINT32 BSP_SetBand(CAL_SRC_T ePll, UINT32 u4CalEn, UINT32 u4Band);
extern UINT32 BSP_SetVConDebugOut(CAL_SRC_T ePll);



#endif  // X_CKGEN_H

