#include "gpio_drv.h"

#include "dw_apb_gpio.h"
#include "ucp_utility.h"
#include "ucp_param.h"
#include "phy_para.h"
#include "ecs_rfm_dm_mgt.h"

//stGpioOnBoard* pGpioInfo = (stGpioOnBoard*)0x0A4D7400;

uint32_t   gGpioDirAddr[4] = {GPIO0A_DIR_REG_ADDR, GPIO0B_DIR_REG_ADDR, GPIO1A_DIR_REG_ADDR, GPIO1B_DIR_REG_ADDR};
uint32_t   gGpioDataAddr[4] = {GPIO0A_DATA_REG_ADDR, GPIO0B_DATA_REG_ADDR, GPIO1A_DATA_REG_ADDR, GPIO1B_DATA_REG_ADDR};

int32_t hw_gpio_init()
{
	if (PROTOCOL_JESD == get_protocol_sel())
	{
		volatile uint32_t h1Pos = 0;
		uint32_t nGpioPin = 0;
		uint8_t i = 0;
		uint8_t j = 0;
		uint8_t k = 0;
		uint8_t pinId = 0;
		uint32_t pinAddr = 0;

	    EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
		stGpioOnBoard* pGpioInfo = pEcsDmLocalMgt->pGpioInfo;

		for (i = 0; i < JESD_GPIOGROUP_NUM; i++) // tx, rx, orx, trans_tx, trans_rx, trans_orx
		{
			k = 0;
			for (j = 0; j < 4; j++)
			{
				nGpioPin = do_read_volatile(GPIO_JESD_RF_BIT + (i<<5) + (j<<2));
				h1Pos = __builtin_clz(nGpioPin); // 从高bit开始，第一个1前面的0的个数
				while (32 > h1Pos)
				{
					pinId = 31 - h1Pos;
					pinAddr = (uint32_t)(&pGpioInfo->jesdGpioInfo.txTransGpioInfo[k].pinId) + sizeof(stGpioInfo) * JESD_RF_CH_NUM * i;
					do_write_byte(pinAddr, (pinId + (j<<5)));
					do_write_byte((pinAddr+1), ((do_read_volatile(GPIO_JESD_RF_VALID + (i<<5) + (j<<2)) >> pinId) & 0x1));
					do_write(gGpioDirAddr[j], (do_read_volatile(gGpioDirAddr[j])|(1<<pinId)));
					k++;
					if (JESD_RF_CH_NUM < k)
					{
						return -1;
					}
					
					nGpioPin &= (~(1 << pinId));
					h1Pos = __builtin_clz(nGpioPin);
				}
			}
		}

        stRfGpioInfo* pRfGpio = NULL;
		uint32_t pinNum = 0;
		uint32_t pinValid = 0;
		for (i = 0; i < JESD_GPIOGROUP_NUM; i++) // tx, rx, orx, trans_tx, trans_rx, trans_orx
		{
			for (j = 0; j < JESD_RF_CH_NUM; j++)
			{
				pRfGpio = pGpioInfo->jesdGpioInfo.txRfGpioInfo + ((i/3)*JESD_RF_CH_NUM+j); //*sizeof(stRfGpioInfo);
				pinNum = do_read_volatile(GPIO_JESD_RF_BIT + (i<<5) + (j<<2));
				pRfGpio->pinInfo |= pinNum;
			    pinValid = do_read_volatile(GPIO_JESD_RF_VALID + (i<<5) + (j<<2));
				pRfGpio->validInfo |= pinValid;
				__ucps2_synch(0);
			    do_write((0x0A4F4000+((i*4+j)<<2)), (uint32_t)(&(pRfGpio->pinInfo)));
			    do_write((0x0A4F4100+((i*4+j)<<2)), (pRfGpio->pinInfo));
			    do_write((0x0A4F4200+((i*4+j)<<2)), (GPIO_JESD_RF_BIT + (i<<5) + (j<<2)));
			    do_write((0x0A4F4300+((i*4+j)<<2)), (pinNum));
			}
		}

		k = 0;
		for (j = 0; j < 4; j++)
		{
			nGpioPin = do_read_volatile(GPIO_JESD_TRIGGER_BIT + (j<<2));
			h1Pos = __builtin_clz(nGpioPin); // 从高bit开始，第一个1前面的0的个数
			while (32 > h1Pos)
			{
				pinId = 31 - h1Pos;
				pinAddr = (uint32_t)(&pGpioInfo->triggerGpioInfo.pinId);
				do_write_byte(pinAddr, (pinId + (j<<5)));
				do_write_byte((pinAddr+1), ((do_read_volatile(GPIO_JESD_TRIGGER_VALID + (j<<2)) >> pinId) & 0x1));
				do_write(gGpioDirAddr[j], (do_read_volatile(gGpioDirAddr[j])|(1<<pinId)));
				k++;
				
				break;
				
				//nGpioPin &= (~(1 << pinId));
				///h1Pos = __builtin_clz(nGpioPin);
			}
		}
	}
	else
	{
		do_write(RF_LVDS_PMUX1_REG_ADDR, (do_read_volatile(RF_LVDS_PMUX1_REG_ADDR)|0x030C0000));	// pinmux, GPIO1B25 and GPIO1B28, gpio func, 0x3
		do_write(GPIO1B_DIR_REG_ADDR, (do_read_volatile(GPIO1B_DIR_REG_ADDR)|(BIT25)|(BIT28)));				// GPIO1B25, output, 10ms trigger for phy
	}

	return 0;
}

int32_t set_jesd_rf_state(uint8_t nTRCh, uint8_t nState)
{
	if (JESD_TRCH_MAXNUM <= nTRCh)
	{
		return -1;
	}
	if ((GPIO_ON != nState) && (GPIO_OFF != nState))
	{
		return -1;
	}

    EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
	stGpioOnBoard* pGpioInfo = pEcsDmLocalMgt->pGpioInfo;

	uint8_t pinGroup = 0;
	uint8_t pinId = 0;
	uint8_t valid = 0;
	uint32_t dataAddr = 0;
	uint32_t pinAddr = 0;
	uint32_t validAddr = 0;
	
	for (int32_t i = 0; i < JESD_RF_CH_NUM; i++)
	{
		pinAddr = (uint32_t)(&pGpioInfo->jesdGpioInfo.txTransGpioInfo[i].pinId) + sizeof(stGpioInfo)*JESD_RF_CH_NUM*nTRCh;
		validAddr = (uint32_t)(&pGpioInfo->jesdGpioInfo.txTransGpioInfo[i].vaFlag) + sizeof(stGpioInfo)*JESD_RF_CH_NUM*nTRCh;
		pinId = do_read_volatile_byte(pinAddr);
		valid = do_read_volatile_byte(validAddr);
		
		pinGroup = pinId >> 5;
		if (3 < pinGroup)
		{
			return -1;
		}
		pinId = pinId & 0x1F;
		dataAddr = gGpioDataAddr[pinGroup];
		if (((LOW_AS_VALID == valid) && (GPIO_ON == nState)) || ((HIGH_AS_VALID == valid) && (GPIO_OFF == nState)))
		{
			do_write(dataAddr, (do_read_volatile(dataAddr)&(~(1<<pinId))));
		__ucps2_synch(0);
		}
		else if (((LOW_AS_VALID == valid) && (GPIO_OFF == nState)) || ((HIGH_AS_VALID == valid) && (GPIO_ON == nState)))
		{
			do_write(dataAddr, (do_read_volatile(dataAddr)|(1<<pinId)));
		__ucps2_synch(0);
		}
		else
		{
			return -1;
		}
	}

	return 0;
}

int32_t set_jesd_all_rf_state(uint8_t nTRCh, uint8_t nState) // tx, rx, orx
{
	EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
	stGpioOnBoard* pGpioInfo = pEcsDmLocalMgt->pGpioInfo;
	uint32_t regData = 0;
	uint32_t tempData = 0;
	uint32_t gpioVal = 0;

	stRfGpioInfo* pRfGpio = pGpioInfo->jesdGpioInfo.txRfGpioInfo + nTRCh*JESD_RF_CH_NUM; //*sizeof(stRfGpioInfo);

	for (uint8_t i = 0; i < JESD_RF_CH_NUM; i++) // 128pin, 4 group
	{
		regData = do_read_volatile(gGpioDataAddr[i]);
		tempData = regData & (~pRfGpio[i].pinInfo);
		
		if (GPIO_ON == nState)
		{
		    gpioVal = pRfGpio[i].pinInfo & pRfGpio[i].validInfo;
		}
		else if (GPIO_OFF == nState)
		{
		    gpioVal = pRfGpio[i].pinInfo ^ pRfGpio[i].validInfo;
		}
		else
		{
		    return -1;
		}

		regData = tempData | gpioVal;
		do_write(gGpioDataAddr[i], regData);
	}

    return 0;
}

int32_t set_trigger_state(uint8_t nState)
{
	if ((GPIO_ON != nState) && (GPIO_OFF != nState))
	{
		return -1;
	}
	if (PROTOCOL_JESD == get_protocol_sel())
	{
	    EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
		stGpioOnBoard* pGpioInfo = pEcsDmLocalMgt->pGpioInfo;

		uint8_t pinGroup = 0;
		uint8_t pinId = 0;
		uint8_t valid = 0;
		uint32_t dataAddr = 0;
		
		pinId = pGpioInfo->triggerGpioInfo.pinId;
		valid =  pGpioInfo->triggerGpioInfo.vaFlag;
		pinGroup = pinId >> 5;
		if (3 < pinGroup)
		{
			return -1;
		}
		pinId = pinId & 0x1F;
		dataAddr = gGpioDataAddr[pinGroup];
		if (((LOW_AS_VALID == valid) && (GPIO_ON == nState)) ||	((HIGH_AS_VALID == valid) && (GPIO_OFF == nState)))
		{
			do_write(dataAddr, (do_read_volatile(dataAddr)&(~(1<<pinId))));
		}
		else if (((LOW_AS_VALID == valid) && (GPIO_OFF == nState)) || ((HIGH_AS_VALID == valid) && (GPIO_ON == nState)))
		{
			do_write(dataAddr, (do_read_volatile(dataAddr)|(1<<pinId)));
		}
		else
		{
			return -1;
		}
	}
	else
	{
		if (GPIO_ON == nState)
		{
			do_write(GPIO1B_DATA_REG_ADDR, (do_read_volatile(GPIO1B_DATA_REG_ADDR)|BIT25|BIT28)); // GPIO1B25 and GPIO1B28, high
		}
		else
		{
			do_write(GPIO1B_DATA_REG_ADDR, (do_read_volatile(GPIO1B_DATA_REG_ADDR)&(~(BIT25))&(~(BIT28)))); // GPIO1B25 and GPIO1B28, low
		}
	}

	return 0;
}


