/* 2012-09-16: File added and changed by Sony Corporation */
/*
 * icx_gpio.c
 *
 * Copyright 2011 Sony Corporation.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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 the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */

#include <common.h>

#if defined(CONFIG_ICX) || defined(CONFIG_ICD)

#include <asm/errno.h>

#include "reg.h"
#include "icx_io.h"
#include "icx_gpio.h"

/********************/
/*@ global routines */
/********************/

/*-----------------------------------------------------------------------------
 *  Function    : gpio_set_direction
 *  Abstruct    : Set a direction of GPIO
 *  Input       : gpio		: GPIO No.
 *              : dir		: input or output
 *  Return      : 0(success) / -EEINVAL
 *----------------------------------------------------------------------------*/
int gpio_set_direction(u_int gpio, int dir)
{
	u_int reg;

	if (gpio < 32)
		reg = dir ? GIO_000_E0 : GIO_000_E1;
	else if (gpio < 64)
		reg = dir ? GIO_032_E0 : GIO_032_E1;
	else if (gpio < 96)
		reg = dir ? GIO_064_E0 : GIO_064_E1;
	else if (gpio < 128)
		reg = dir ? GIO_096_E0 : GIO_096_E1;
	else if (gpio <= 158)
		reg = dir ? GIO_128_E0 : GIO_128_E1;
	else
		return -EINVAL;

	outl((1U << (gpio & 0x0000001F)), reg);

	return 0;
}

/*-----------------------------------------------------------------------------
 *  Function    : gpio_set_value
 *  Abstruct    : Set a value to GPIO
 *  Input       : gpio		: GPIO No.
 *              : val		: Value
 *  Return      : 0(success) / -EINVAL
 *----------------------------------------------------------------------------*/
int gpio_set_value(u_int gpio, int val)
{
	u_int gio_oe, gio_od;

	gio_oe = 0x10000U << (gpio & 0x0000000F);
	gio_od = val ? (0x1U << (gpio & 0x0000000F)) : 0;

	if (gpio < 16)
		outl((gio_oe | gio_od), GIO_000_OL);
	else if (gpio < 32)
		outl((gio_oe | gio_od), GIO_000_OH);
	else if (gpio < 48)
		return -EINVAL;
	else if (gpio < 64)
		outl((gio_oe | gio_od), GIO_032_OH);
	else if (gpio < 80)
		outl((gio_oe | gio_od), GIO_064_OL);
	else if (gpio < 96)
		outl((gio_oe | gio_od), GIO_064_OH);
	else if (gpio < 112)
		outl((gio_oe | gio_od), GIO_096_OL);
	else if (gpio < 128)
		outl((gio_oe | gio_od), GIO_096_OH);
	else if (gpio < 144)
		outl((gio_oe | gio_od), GIO_128_OL);
	else if (gpio <= 158)
		outl((gio_oe | gio_od), GIO_128_OH);
	else
		return -EINVAL;

	return 0;
}

/*-----------------------------------------------------------------------------
 *  Function    : gpio_get_value
 *  Abstruct    : get a value from GPIO
 *  Input       : gpio : GPIO number
 *  Return      : 0:low 1:high minus:error
 *----------------------------------------------------------------------------*/
int gpio_get_value(u_int gpio)
{
	u_int mask;
	int val;

	mask = 1 << (gpio & 0x0000001F);

	if (gpio < 32)
		val=inl(GIO_000_I);
	else if (gpio < 64)
		val=inl(GIO_032_I);
	else if (gpio < 96)
		val=inl(GIO_064_I);
	else if (gpio < 128)
		val=inl(GIO_096_I);
	else if (gpio <= 158)
		val=inl(GIO_128_I);
	else
		return -EINVAL;

	return ((val & mask) ? 1 : 0);
}

#endif	/* CONFIG_ICX || CONFIG_ICD */ 
