/*
 * Driver for Altera's PIO ip core
 *
 * Copyright (C) 2011  Missing Link Electronics
 *                     Joachim Foerster <joachim@missinglinkelectronics.com>
 *
 * 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
 *
 * To use this driver, in your board's config. header:
 * #define CONFIG_ALTERA_PIO
 * #define CONFIG_SYS_ALTERA_PIO_NUM <number-of-pio-cores>
 * #define CONFIG_SYS_ALTERA_PIO_GPIO_NUM <total-number-of-gpios>
 * And in your board's early setup routine:
 * altera_pio_init(<baseaddr>, <width>, 'i'|'o'|'t',
 *                 <reset-value>, <neg-mask>, "label");
 *  - 'i'|'o'|'t': PIO is input-only/output-only/tri-state
 *  - <reset-value>: for correct initial status display, output-only
 *  - <neg-mask> is meant to be used to in cases of active-low
 *    GPIOs, such as LEDs and buttons (on/pressed == 0). Each bit
 *    which is 1 in <neg-mask> inverts the corresponding GPIO's value
 *    before set/after get. So: gpio_set_value(gpio, 1) => LED on .
 *
 * Do NOT define CONFIG_SYS_GPIO_BASE !
 *
 * Optionally, in your board's config. header:
 * - To force a GPIO numbering scheme like in Linux ...
 * #define CONFIG_GPIO_DOWNTO_NUMBERING
 * ... starting with 255 (default)
 * #define CONFIG_GPIO_DOWNTO_MAX 255
 */
#include <common.h>
#include <asm/io.h>
#include <asm/gpio.h>

#ifdef CONFIG_GPIO_DOWNTO_NUMBERING
#ifndef CONFIG_GPIO_DOWNTO_MAX
#define CONFIG_GPIO_DOWNTO_MAX 255
#endif
#endif

#define ALTERA_PIO_DATA		0x0
#define ALTERA_PIO_DIR		0x4

#define GPIO_LABEL_SIZE		9


static struct altera_pio {
	u32 base;
	u8 width;
	char iot;
	u32 negmask;
	u32 sh_data;
	u32 sh_dir;
	int gidx;
	char label[GPIO_LABEL_SIZE];
} pios[CONFIG_SYS_ALTERA_PIO_NUM];

static int pio_num;

static struct altera_pio_gpio {
	unsigned num;
	struct altera_pio *pio;
	char reqlabel[GPIO_LABEL_SIZE];
} gpios[CONFIG_SYS_ALTERA_PIO_GPIO_NUM];

static int pio_gpio_num;


static int altera_pio_gidx(unsigned gpio)
{
	int i;

	for (i = 0; i < pio_gpio_num; ++i) {
		if (gpio == gpios[i].num)
			break;
	}
	if (i >= pio_gpio_num)
		return -1;
	return i;
}

static struct altera_pio *altera_pio_get_and_mask(unsigned gpio, u32 *mask)
{
	int gidx = altera_pio_gidx(gpio);
	if (gidx < 0)
		return NULL;
	if (mask)
		*mask = 1 << (gidx - gpios[gidx].pio->gidx);
	return gpios[gidx].pio;
}

#define altera_pio_use_gidx(_gidx, _reqlabel) \
	{ strncpy(gpios[_gidx].reqlabel, _reqlabel, GPIO_LABEL_SIZE); }
#define altera_pio_unuse_gidx(_gidx) { gpios[_gidx].reqlabel[0] = '\0'; }
#define altera_pio_is_gidx_used(_gidx) (gpios[_gidx].reqlabel[0] != '\0')

static int altera_pio_gpio_init(struct altera_pio *pio, u8 width)
{
	u8 gidx = pio_gpio_num;
	int i;

	if (!width)
		return -1;
	if ((pio_gpio_num + width) > CONFIG_SYS_ALTERA_PIO_GPIO_NUM)
		return -1;

	for (i = 0; i < width; ++i) {
#ifdef CONFIG_GPIO_DOWNTO_NUMBERING
		gpios[pio_gpio_num + i].num = \
			CONFIG_GPIO_DOWNTO_MAX + 1 - gidx - width + i;
#else
		gpios[pio_gpio_num + i].num = pio_gpio_num + i;
#endif
		gpios[pio_gpio_num + i].pio = pio;
		altera_pio_unuse_gidx(pio_gpio_num + i);
	}
	pio_gpio_num += width;
	return gidx;
}

int altera_pio_init(u32 base, u8 width, char iot, u32 rstval, u32 negmask,
		 const char *label)
{
	if (pio_num >= CONFIG_SYS_ALTERA_PIO_NUM)
		return -1;

	pios[pio_num].base = base;
	pios[pio_num].width = width;
	pios[pio_num].iot = iot;
	switch (iot) {
	case 'i':
		/* input only */
		pios[pio_num].sh_dir = 0;
		pios[pio_num].sh_data = readl(base + ALTERA_PIO_DATA);
		break;
	case 'o':
		/* output only */
		pios[pio_num].sh_dir = 0xffffffff & ((1 << width) - 1);
		pios[pio_num].sh_data = rstval;
		break;
	case 't':
		/* bidir, tri-state */
		pios[pio_num].sh_dir = readl(base + ALTERA_PIO_DIR);
		pios[pio_num].sh_data = readl(base + ALTERA_PIO_DATA);
		break;
	default:
		return -1;
	}
	pios[pio_num].negmask = negmask & ((1 << width) - 1);
	pios[pio_num].gidx = altera_pio_gpio_init(&pios[pio_num], width);
	if (pios[pio_num].gidx < 0)
		return -1;
	strncpy(pios[pio_num].label, label, GPIO_LABEL_SIZE);
	return pio_num++;
}

void altera_pio_info(void)
{
	int i;
	int j;
	int gidx;
	u32 mask;

	for (i = 0; i < pio_num; ++i) {
		printf("Altera PIO % 2d, @0x%08x, "
			"width: %u, label: %s\n",
		       i, pios[i].base, pios[i].width, pios[i].label);
		gidx = pios[i].gidx;
		for (j = gidx; j < (gidx + pios[i].width); ++j) {
			mask = 1 << (j - gidx);
			printf("\tGPIO % 4d: %s %s [%c] %s\n",
				gpios[j].num,
				gpios[j].pio->sh_dir & mask ? "out" : " in",
				gpio_get_value(gpios[j].num) ? "set" : "clr",
				altera_pio_is_gidx_used(j) ? 'x' : ' ',
				gpios[j].reqlabel);
		}
	}
}


int gpio_request(unsigned gpio, const char *label)
{
	int gidx = altera_pio_gidx(gpio);
	if (gidx < 0)
		return gidx;
	if (altera_pio_is_gidx_used(gidx))
		return -1;

	altera_pio_use_gidx(gidx, label);
	return 0;
}

int gpio_free(unsigned gpio)
{
	int gidx = altera_pio_gidx(gpio);
	if (gidx < 0)
		return gidx;
	if (!altera_pio_is_gidx_used(gidx))
		return -1;

	altera_pio_unuse_gidx(gidx);
	return 0;
}

int gpio_direction_input(unsigned gpio)
{
	u32 mask;
	struct altera_pio *pio;

	pio = altera_pio_get_and_mask(gpio, &mask);
	if (!pio)
		return -1;
	if (pio->iot == 'o')
		return -1;

	writel(pio->sh_dir &= ~mask, pio->base + ALTERA_PIO_DIR);
	return 0;
}

int gpio_direction_output(unsigned gpio, int value)
{
	u32 mask;
	struct altera_pio *pio;

	pio = altera_pio_get_and_mask(gpio, &mask);
	if (!pio)
		return -1;
	if (pio->iot == 'i')
		return -1;

	value = (pio->negmask & mask) ? !value : value;
	if (value)
		pio->sh_data |= mask;
	else
		pio->sh_data &= ~mask;
	writel(pio->sh_data, pio->base + ALTERA_PIO_DATA);
	writel(pio->sh_dir |= mask, pio->base + ALTERA_PIO_DIR);
	return 0;
}

int gpio_get_value(unsigned gpio)
{
	u32 mask;
	struct altera_pio *pio;
	u32 val;

	pio = altera_pio_get_and_mask(gpio, &mask);
	if (!pio)
		return -1;

	if ((pio->sh_dir & mask) || (pio->iot == 'o'))
		val = pio->sh_data & mask;
	else
		val = readl(pio->base + ALTERA_PIO_DATA) & mask;
	return (pio->negmask & mask) ? !val : val;
}

void gpio_set_value(unsigned gpio, int value)
{
	u32 mask;
	struct altera_pio *pio;

	pio = altera_pio_get_and_mask(gpio, &mask);
	if (!pio)
		return;
	if (pio->iot == 'i')
		return;

	value = (pio->negmask & mask) ? !value : value;
	if (value)
		pio->sh_data |= mask;
	else
		pio->sh_data &= ~mask;
	writel(pio->sh_data, pio->base + ALTERA_PIO_DATA);
	return;
}

int gpio_is_valid(int number)
{
	int gidx = altera_pio_gidx(number);

	if (gidx < 0)
		return 1;
	return 0;
}
