/*******************************************************************************
** Document: w747_gpio_function.c
** Copyright (c) 2004 R&D Center, Tailyn Communication Company, Ltd.  
** Created by: Chien Chung Lo
** Date: Dec. 6, 2004
** Description: Wintegra GPIO device function.
** Version: 0.1
*******************************************************************************/

#include <asm/io.h>

#include "w747_gpio_function.h"
#include "w747_gpio.h"

volatile struct gpio_a_value_struct* gpio_a = (struct gpio_a_value_struct*)W747_GPIO_GPVR_A_REG;
volatile struct gpio_c_value_struct* gpio_c = (struct gpio_c_value_struct*)W747_GPIO_GPVR_C_REG;
volatile struct gpio_e_value_struct* gpio_e = (struct gpio_e_value_struct*)W747_GPIO_GPVR_E_REG;

//----------------------------------------------------------------------
//
//----------------------------------------------------------------------
int w747_init_gpio(void)
{
	unsigned int value;
	
	//show_gpio_reg();
	
	//-------------------------------------------
	//	set gpio mode
	//-------------------------------------------
	value = inl_p(W747_GPIO_GPCR_A_REG);
	value = value & GPIO_A_SETTING;
	outl_p(value, W747_GPIO_GPCR_A_REG);
	
	value = inl_p(W747_GPIO_GPCMR_A_REG);	
	value = value & GPIO_A_SETTING;
	outl_p(value, W747_GPIO_GPCMR_A_REG);	

	value = inl_p(W747_GPIO_GPCR_C_REG);	
	value = value & GPIO_C_SETTING;
	outl_p(value, W747_GPIO_GPCR_C_REG);	
	
	value = inl_p(W747_GPIO_GPCMR_C_REG);	
	value = value & GPIO_C_SETTING;
	outl_p(value, W747_GPIO_GPCMR_C_REG);	

	value = inl_p(W747_GPIO_GPCR_E_REG);	
	value = value & GPIO_E_SETTING;
	outl_p(value, W747_GPIO_GPCR_E_REG);	
		
	value = inl_p(W747_GPIO_GPCMR_E_REG);	
	value = value & GPIO_E_SETTING;
	outl_p(value, W747_GPIO_GPCMR_E_REG);	
	
	//-------------------------------------------
	//	set gpio direction
	//-------------------------------------------
	value = inl_p(W747_GPIO_GPDR_A_REG);	
	value = value | GPIO_A_DIR;
	outl_p(value, W747_GPIO_GPDR_A_REG);	
	
	value = inl_p(W747_GPIO_GPDR_C_REG);	
	value = value | GPIO_C_DIR;
	outl_p(value, W747_GPIO_GPDR_C_REG);	

	value = inl_p(W747_GPIO_GPDR_E_REG);	
	value = value | GPIO_E_DIR;
	outl_p(value, W747_GPIO_GPDR_E_REG);

	//-------------------------------------------
	//	initial value of gpio
	//-------------------------------------------
	// GPIO C
	gpio_set(I2C_SEL);
	gpio_clr(ALARM_LED_1);
	gpio_clr(ALARM_LED_2);
	gpio_clr(SYSTEM_LED_1);
	gpio_clr(SYSTEM_LED_2);
	
	// GPIO E
	gpio_clr(BP_HBUS_CTRL_0);
	gpio_clr(BP_HBUS_CTRL_1);
	gpio_clr(BP_HBUS_CTRL_2);
	gpio_clr(BP_HBUS_CTRL_3);
	gpio_clr(BP_HBUS_CTRL_4);
	gpio_set(BP_SW_RST_0);
	gpio_set(BP_SW_RST_1);
	gpio_set(BP_SW_RST_2);
	gpio_set(BP_SW_RST_3);
	gpio_set(BP_SW_RST_4);
	gpio_set(BP_ALARM_1);
	gpio_set(BP_ALARM_2);
	gpio_set(ALL_BUS_ENABLE);
	gpio_clr(ETH_RST);
	gpio_set(BP_FAN_ENABLE);
	gpio_clr(GIGA_RST);
	
	//show_gpio_reg();
	
	return 0;  // success!!	
}

//----------------------------------------------------------------------
//
//----------------------------------------------------------------------
int gpio_read(unsigned int gpio_pin)
{
	unsigned int value;
	
	if(gpio_pin < GPIO_C_BASE)
	{
		value = inl_p(W747_GPIO_GPVR_A_REG);
		value = (value >> gpio_pin) & 0x1;
		return value;
	}
	else if(gpio_pin >= GPIO_C_BASE && gpio_pin < GPIO_E_BASE)
	{
		value = inl_p(W747_GPIO_GPVR_C_REG);
		value = (value >> (gpio_pin - GPIO_C_BASE)) & 0x1;
		return value;
	}
	else if(gpio_pin >= GPIO_E_BASE && gpio_pin < MAX_GPIO_NUM)
	{
		value = inl_p(W747_GPIO_GPVR_E_REG);
		value = (value >> (gpio_pin - GPIO_E_BASE)) & 0x1;
		return value;
	}
	
	return -EINVAL;
}

//----------------------------------------------------------------------
//
//----------------------------------------------------------------------
int gpio_set(unsigned int gpio_pin)
{
	unsigned int value;
	
	if(gpio_pin >= GPIO_C_BASE && gpio_pin < GPIO_E_BASE)
	{
		value = inl_p(W747_GPIO_GPVR_C_REG);
		value = value | (unsigned int)(1 << (gpio_pin - GPIO_C_BASE));
		outl_p(value, W747_GPIO_GPVR_C_REG);
		return 0;
	}
	else if(gpio_pin >= GPIO_E_BASE && gpio_pin < MAX_GPIO_NUM)
	{
		value = inl_p(W747_GPIO_GPVR_E_REG);
		value = value | (unsigned int)(1 << (gpio_pin - GPIO_E_BASE));
		outl_p(value, W747_GPIO_GPVR_E_REG);
		return 0;	
	}
	
	return -EINVAL;	
}

//----------------------------------------------------------------------
//
//----------------------------------------------------------------------
int gpio_clr(unsigned int gpio_pin)
{
	unsigned int value;
	
	if(gpio_pin >= GPIO_C_BASE && gpio_pin < GPIO_E_BASE)
	{
		value = inl_p(W747_GPIO_GPVR_C_REG);
		value = value & (unsigned int)(~(1 << (gpio_pin - GPIO_C_BASE)));
		outl_p(value, W747_GPIO_GPVR_C_REG);
		return 0;
	}
	
	else if(gpio_pin >= GPIO_E_BASE && gpio_pin < MAX_GPIO_NUM)
	{
		value = inl_p(W747_GPIO_GPVR_E_REG);
		value = value & (unsigned int)(~(1 << (gpio_pin - GPIO_E_BASE)));
		outl_p(value, W747_GPIO_GPVR_E_REG);
		return 0;
	}
	
	return -EINVAL; // fail !!
}
/*
void show_gpio_reg(void)
{
	unsigned int value;
	
	MSG("address:%x\n", (unsigned int)W747_GPIO_GPCR_A_REG);
	
	value = inl_p(W747_GPIO_GPCR_A_REG);
	MSG("GPIO A GPCR  data:%x\n", value);
	value = inl_p(W747_GPIO_GPDR_A_REG);
	MSG("GPIO A GPDR  data:%x\n", value);
	value = inl_p(W747_GPIO_GPVR_A_REG);
	MSG("GPIO A GPVR  data:%x\n", value);
	value = inl_p(W747_GPIO_GPCMR_A_REG);
	MSG("GPIO A GPCMR data:%x\n", value);
	
	value = inl_p(W747_GPIO_GPCR_C_REG);
	MSG("GPIO C GPCR  data:%x\n", value);
	value = inl_p(W747_GPIO_GPDR_C_REG);
	MSG("GPIO C GPDR  data:%x\n", value);
	value = inl_p(W747_GPIO_GPVR_C_REG);
	MSG("GPIO C GPVR  data:%x\n", value);
	value = inl_p(W747_GPIO_GPCMR_C_REG);
	MSG("GPIO C GPCMR data:%x\n", value);
	
	value = inl_p(W747_GPIO_GPCR_E_REG);
	MSG("GPIO E GPCR  data:%x\n", value);
	value = inl_p(W747_GPIO_GPDR_E_REG);
	MSG("GPIO E GPDR  data:%x\n", value);
	value = inl_p(W747_GPIO_GPVR_E_REG);
	MSG("GPIO E GPVR  data:%x\n", value);
	value = inl_p(W747_GPIO_GPCMR_E_REG);
	MSG("GPIO E GPCMR data:%x\n\n", value);
}
*/


