/* 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 MTK_SIF_CFG_H
#define MTK_SIF_CFG_H

#include "x_gpio.h"

#include "x_timer.h"
#include "x_pinmux.h"
#include "x_os.h"
#include "x_assert.h"
#include "drvcust_if.h"
#include "pcmcia_if.h"

extern INT8 SIF_MtkCfgPinSetFunc(UINT8 u1Channel);

#define SIF_CFG_PIN_SET_FUNC     (SIF_MtkCfgPinSetFunc)

#if !defined(CONFIG_I2C_MT53XX) && !defined(CC_UBOOT)

static SIF_CONFIG_T _rSifConfig;

//#define SIF_CFG_BEFORE_ACTION_FUNC      (SIF_MtkCfgBeforeActionFunc)
//#define SIF_CFG_AFTER_ACTION_FUNC     (SIF_MtkCfgAfterActionFunc)

#define SIF_CFG_GET_CONFIG_FUNC     (SIF_MtkCfgGetConfigFunc)
//#define SIF_CFG_TRI_DELAY (0)
//#define SIF_CFG_TRI_DELAY_DEV_ADDR (0)

extern SIF_CONFIG_T* SIF_MtkCfgGetConfigFunc(void);
#else
#define SIF_CFG_GET_CONFIG_FUNC  (NULL)

#endif
#endif /* MTK_SIF_CFG */

// this array only works for 5893
#ifdef CC_S_PLATFORM
INT8 SIF_ChannelMap[SIF_MAX_NUM_MASTER+1]={0,1,2,3,4,5,-1};
#else
INT8 SIF_ChannelMap[SIF_MAX_NUM_MASTER+1]={0,1,2,3,4,-1,-1};
#endif

#if !defined(CONFIG_I2C_MT53XX) && !defined(CC_UBOOT)

static SIF_CONFIG_T _rSifConfig =
{
	7, // Total 7 buses
	{
		0, 		// SystemI2C uses Master0
		1, 		// TunerI2C uses Master1
		2,		// SecondI2C uses Master2
		3, 		// PdwncI2C uses Pdwnc Master0
		4, 		// PdwncI2C1 uses Pdwnc Master1
		5, 		// Third I2C uses Master3
		1		// HDMI debug I2C uses Master1
	}
};

extern SIF_CONFIG_T* SIF_MtkCfgGetConfigFunc(void)
{
	return &_rSifConfig;
}

#endif

extern INT8 SIF_MtkCfgPinSetFunc(UINT8 u1Channel)
{
	if(SIF_ChannelMap[u1Channel] == -1)
		return -1;
#if !defined(CONFIG_I2C_MT53XX) && !defined(CC_UBOOT)

	if (u1Channel == 0)	//osda0/oscl0, for eeprom use
	{
    	if(_rSifConfig.au1Master[0] == 0)
    	{
    		//channel 0 to master 0
			BSP_PinSet(PIN_OSCL0,PINMUX_FUNCTION1);
			BSP_PinSet(PIN_OSDA0,PINMUX_FUNCTION1);

			if(2==BSP_PinGet(PIN_OSCL1) || 2==BSP_PinGet(PIN_OSDA1))
			{
				BSP_PinSet(PIN_OSCL1,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA1,PINMUX_FUNCTION0);
			}
			if(1==BSP_PinGet(PIN_OSCL2) || 1==BSP_PinGet(PIN_OSDA2))
			{
				BSP_PinSet(PIN_OSCL2,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA2,PINMUX_FUNCTION0);
			}
    	}
		else if(_rSifConfig.au1Master[0] == 1)
		{
			//channel 0 to master 1
			BSP_PinSet(PIN_OSCL0,PINMUX_FUNCTION2);
			BSP_PinSet(PIN_OSDA0,PINMUX_FUNCTION2);

			if(1==BSP_PinGet(PIN_OSCL1) || 1==BSP_PinGet(PIN_OSDA1))
			{
				BSP_PinSet(PIN_OSCL1,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA1,PINMUX_FUNCTION0);
			}
			if(2==BSP_PinGet(PIN_OSCL2) || 2==BSP_PinGet(PIN_OSDA2))
			{
				BSP_PinSet(PIN_OSCL2,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA2,PINMUX_FUNCTION0);
			}
			
		}
		else if(_rSifConfig.au1Master[0] == 2)
		{
			//channel 0 to master 2
			BSP_PinSet(PIN_OSCL0,PINMUX_FUNCTION4);
			BSP_PinSet(PIN_OSDA0,PINMUX_FUNCTION4);
			if(3==BSP_PinGet(PIN_OSCL2) || 3==BSP_PinGet(PIN_OSDA2))
			{
				BSP_PinSet(PIN_OSCL2,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA2,PINMUX_FUNCTION0);
			}	
		}
        else if(_rSifConfig.au1Master[0] == 5)
        {
            BSP_PinSet(PIN_OSCL0,PINMUX_FUNCTION3);
            BSP_PinSet(PIN_OSDA0,PINMUX_FUNCTION3);
            if(3==BSP_PinGet(PIN_OSCL1) || 3==BSP_PinGet(PIN_OSDA1))
            {
                BSP_PinSet(PIN_OSCL1,PINMUX_FUNCTION0);
                BSP_PinSet(PIN_OSDA1,PINMUX_FUNCTION0);
            }			
        }
		else
		{		
			BSP_PinSet(PIN_OSCL0,PINMUX_FUNCTION0);
			BSP_PinSet(PIN_OSDA0,PINMUX_FUNCTION0);			
		}
    }
    else if (u1Channel == 1)	//osda2/oscl2, for tuner use.
    {
    	if(_rSifConfig.au1Master[1] == 0)
    	{
    		//channel 1 to master 0
    		BSP_PinSet(PIN_OSCL1,PINMUX_FUNCTION2);
			BSP_PinSet(PIN_OSDA1,PINMUX_FUNCTION2);

			if(1==BSP_PinGet(PIN_OSCL0) || 1==BSP_PinGet(PIN_OSDA0))
			{
				BSP_PinSet(PIN_OSCL0,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA0,PINMUX_FUNCTION0);
			}
			if(1==BSP_PinGet(PIN_OSCL2) || 1==BSP_PinGet(PIN_OSDA2))
			{
				BSP_PinSet(PIN_OSCL2,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA2,PINMUX_FUNCTION0);
			}
    	}
		else if(_rSifConfig.au1Master[1] == 1)
		{
			//channel 1 to master 1
    		BSP_PinSet(PIN_OSCL1,PINMUX_FUNCTION1);
			BSP_PinSet(PIN_OSDA1,PINMUX_FUNCTION1);

			if(2==BSP_PinGet(PIN_OSCL0) || 2==BSP_PinGet(PIN_OSDA0))
			{
				BSP_PinSet(PIN_OSCL0,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA0,PINMUX_FUNCTION0);
			}
			if(2==BSP_PinGet(PIN_OSCL2) || 2==BSP_PinGet(PIN_OSDA2))
			{
				BSP_PinSet(PIN_OSCL2,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA2,PINMUX_FUNCTION0);
			}
		}
		else if(_rSifConfig.au1Master[1] == 2)
		{
			//channel 1 to master 3
    		BSP_PinSet(PIN_OSCL1,PINMUX_FUNCTION3);
			BSP_PinSet(PIN_OSDA1,PINMUX_FUNCTION3);

			if(3==BSP_PinGet(PIN_OSCL0) || 3==BSP_PinGet(PIN_OSDA0))
			{
				BSP_PinSet(PIN_OSCL0,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA0,PINMUX_FUNCTION0);
			}	      
		}
		else
		{
	        BSP_PinSet(PIN_OSCL1,PINMUX_FUNCTION0);
			BSP_PinSet(PIN_OSDA1,PINMUX_FUNCTION0);
		}
    }
    else if (u1Channel == 2)	//osda1/oscl1, for other use.
    {
    	if(_rSifConfig.au1Master[2] == 0)
    	{
    		//channel 2 to master 0
    		BSP_PinSet(PIN_OSCL2,PINMUX_FUNCTION1);
			BSP_PinSet(PIN_OSDA2,PINMUX_FUNCTION1);

			if(2==BSP_PinGet(PIN_OSCL1) || 2==BSP_PinGet(PIN_OSDA1))
			{
				BSP_PinSet(PIN_OSCL1,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA1,PINMUX_FUNCTION0);
			}
			if(1==BSP_PinGet(PIN_OSCL0) || 3==BSP_PinGet(PIN_OSDA0))
			{
				BSP_PinSet(PIN_OSCL0,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA0,PINMUX_FUNCTION0);
			}	      
    	}
		else if(_rSifConfig.au1Master[2] == 1)
		{
			//channel 2 to master 1
    		BSP_PinSet(PIN_OSCL2,PINMUX_FUNCTION2);
			BSP_PinSet(PIN_OSDA2,PINMUX_FUNCTION2);

			if(1==BSP_PinGet(PIN_OSCL1) || 1==BSP_PinGet(PIN_OSDA1))
			{
				BSP_PinSet(PIN_OSCL1,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA1,PINMUX_FUNCTION0);
			}
			if(2==BSP_PinGet(PIN_OSCL0) || 2==BSP_PinGet(PIN_OSDA0))
			{
				BSP_PinSet(PIN_OSCL0,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA0,PINMUX_FUNCTION0);
			}	 
		}
		else if(_rSifConfig.au1Master[2] == 2)
		{
			//channel 2 to master 2
    		BSP_PinSet(PIN_OSCL2,PINMUX_FUNCTION3);
			BSP_PinSet(PIN_OSDA2,PINMUX_FUNCTION3);

			if(4==BSP_PinGet(PIN_OSCL0) || 4==BSP_PinGet(PIN_OSDA0))
			{
				BSP_PinSet(PIN_OSCL0,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA0,PINMUX_FUNCTION0);
			}	      	
		}
		else
		{	
			//channel 2 to master 2
			BSP_PinSet(PIN_OSCL2,PINMUX_FUNCTION0);
			BSP_PinSet(PIN_OSDA2,PINMUX_FUNCTION0);
		}
    }
    else if (u1Channel == 3) // PDWNC SIF0
    {
    	if(_rSifConfig.au1Master[3] == 3)
    	{
    		//channel 3 to master 3
    		BSP_PinSet(PIN_OPCTRL0,PINMUX_FUNCTION1);
			BSP_PinSet(PIN_OPCTRL1,PINMUX_FUNCTION1);      	
    	}
    }
    else if (u1Channel == 4) // PDWNC SIF1
    {
    	if(_rSifConfig.au1Master[4] == 4)
    	{
    		//channel 3 to master 3
    		BSP_PinSet(PIN_STB_SCL,PINMUX_FUNCTION1);
			BSP_PinSet(PIN_STB_SDA,PINMUX_FUNCTION1);  
    	}
    }
    else if (u1Channel == 5)	// I2C master3
    {
		if(_rSifConfig.au1Master[5] == 5)
		{
			//channel 5 to master 3
			#ifdef CC_S_PLATFORM  // M5 use OPCTRL2 & 3 for I2C master3 (channel 5)
			BSP_PinSet(PIN_OPCTRL2,PINMUX_FUNCTION4);
			BSP_PinSet(PIN_OPCTRL3,PINMUX_FUNCTION4);
			#else
			BSP_PinSet(PIN_U1RX,PINMUX_FUNCTION3);
			BSP_PinSet(PIN_U1TX,PINMUX_FUNCTION3);
			#endif

			if(3==BSP_PinGet(PIN_OSCL1) || 3==BSP_PinGet(PIN_OSDA1))
			{
				BSP_PinSet(PIN_OSCL1,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA1,PINMUX_FUNCTION0);
			}
			if(3==BSP_PinGet(PIN_OSCL0) || 3==BSP_PinGet(PIN_OSDA0))
			{
				BSP_PinSet(PIN_OSCL0,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA0,PINMUX_FUNCTION0);
			}
    	}
	}
    else if (u1Channel == 6)	//Husky not DTMB_SDA/SCL
    {
    	if(_rSifConfig.au1Master[u1Channel] == 0)
    	{
			//channel 0 to master 0
			BSP_PinSet(PIN_OSCL0,PINMUX_FUNCTION1);
			BSP_PinSet(PIN_OSDA0,PINMUX_FUNCTION1);

			if(2==BSP_PinGet(PIN_OSCL1) || 2==BSP_PinGet(PIN_OSDA1))
			{
				BSP_PinSet(PIN_OSCL1,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA1,PINMUX_FUNCTION0);
			}
			if(1==BSP_PinGet(PIN_OSCL2) || 1==BSP_PinGet(PIN_OSDA2))
			{
				BSP_PinSet(PIN_OSCL2,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA2,PINMUX_FUNCTION0);
			}
    	}
		else if(_rSifConfig.au1Master[u1Channel] == 1)
		{
			//channel 0 to master 1
			BSP_PinSet(PIN_GPIO53,PINMUX_FUNCTION8);
			BSP_PinSet(PIN_GPIO54,PINMUX_FUNCTION8);
			
			if(2==BSP_PinGet(PIN_OSCL0) || 2==BSP_PinGet(PIN_OSDA0))
			{
				BSP_PinSet(PIN_OSCL0,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA0,PINMUX_FUNCTION0);
			}
			if(1==BSP_PinGet(PIN_OSCL1) || 1==BSP_PinGet(PIN_OSDA1))
			{
				BSP_PinSet(PIN_OSCL1,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA1,PINMUX_FUNCTION0);
			}
			if(2==BSP_PinGet(PIN_OSCL2) || 2==BSP_PinGet(PIN_OSDA2))
			{
				BSP_PinSet(PIN_OSCL2,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA2,PINMUX_FUNCTION0);
			}					
		}
		else if(_rSifConfig.au1Master[u1Channel] == 2)
		{	
			//channel 0 to master 1
			BSP_PinSet(PIN_OSDA0,PINMUX_FUNCTION3);
			BSP_PinSet(PIN_OSCL0,PINMUX_FUNCTION3);
			
			if(3==BSP_PinGet(PIN_OSCL1) || 3==BSP_PinGet(PIN_OSDA1))
			{
				BSP_PinSet(PIN_OSCL1,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA1,PINMUX_FUNCTION0);
			}
			if(3==BSP_PinGet(PIN_OSCL2) || 3==BSP_PinGet(PIN_OSDA2))
			{
				BSP_PinSet(PIN_OSCL2,PINMUX_FUNCTION0);
				BSP_PinSet(PIN_OSDA2,PINMUX_FUNCTION0);
			}							
		}
		else
		{
		  	printf("u1Channel master null\n");	
			BSP_PinSet(PIN_OSDA0,PINMUX_FUNCTION3);
			BSP_PinSet(PIN_OSCL0,PINMUX_FUNCTION3);		
		}
    }
	
#endif//allow set pinmux
	return SIF_ChannelMap[u1Channel];
}
