/*
 * Gemini gpiochip and interrupt routines
 *
 * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
 *
 * Based on plat-mxc/gpio.c:
 *  MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
 *  Copyright 2008 Juergen Beisert, kernel@pengutronix.de
 *
 * 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.
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/gpio.h>

#include <mach/hardware.h>
#include <mach/irqs.h>

#define GPIO_BASE(x)		IO_ADDRESS(GEMINI_GPIO_BASE(x))

/* GPIO registers definition */
#define GPIO_DATA_OUT		0x0
#define GPIO_DATA_IN		0x4
#define GPIO_DIR		0x8
#define GPIO_DATA_SET		0x10
#define GPIO_DATA_CLR		0x14
#define GPIO_PULL_EN		0x18
#define GPIO_PULL_TYPE		0x1C
#define GPIO_INT_EN		0x20
#define GPIO_INT_STAT		0x24
#define GPIO_INT_MASK		0x2C
#define GPIO_INT_CLR		0x30
#define GPIO_INT_TYPE		0x34
#define GPIO_INT_BOTH_EDGE	0x38
#define GPIO_INT_LEVEL		0x3C
#define GPIO_DEBOUNCE_EN	0x40
#define GPIO_DEBOUNCE_PRESCALE	0x44

#define GPIO_PORT_NUM		3

static void _set_gpio_irqenable(unsigned int base, unsigned int index,
				int enable)
{
	unsigned int reg;

	reg = __raw_readl(base + GPIO_INT_EN);
	reg = (reg & (~(1 << index))) | (!!enable << index);
	__raw_writel(reg, base + GPIO_INT_EN);
}

static void gpio_ack_irq(unsigned int irq)
{
	unsigned int gpio = irq_to_gpio(irq);
	unsigned int base = GPIO_BASE(gpio / 32);

	__raw_writel(1 << (gpio % 32), base + GPIO_INT_CLR);
}

static void gpio_mask_irq(unsigned int irq)
{
	unsigned int gpio = irq_to_gpio(irq);
	unsigned int base = GPIO_BASE(gpio / 32);

	_set_gpio_irqenable(base, gpio % 32, 0);
}

static void gpio_unmask_irq(unsigned int irq)
{
	unsigned int gpio = irq_to_gpio(irq);
	unsigned int base = GPIO_BASE(gpio / 32);

	_set_gpio_irqenable(base, gpio % 32, 1);
}

static int gpio_set_irq_type(unsigned int irq, unsigned int type)
{
	unsigned int gpio = irq_to_gpio(irq);
	unsigned int gpio_mask = 1 << (gpio % 32);
	unsigned int base = GPIO_BASE(gpio / 32);
	unsigned int reg_both, reg_level, reg_type;

	reg_type = __raw_readl(base + GPIO_INT_TYPE);
	reg_level = __raw_readl(base + GPIO_INT_BOTH_EDGE);
	reg_both = __raw_readl(base + GPIO_INT_BOTH_EDGE);

	switch (type) {
	case IRQ_TYPE_EDGE_BOTH:
		reg_type &= ~gpio_mask;
		reg_both |= gpio_mask;
		break;
	case IRQ_TYPE_EDGE_RISING:
		reg_type &= ~gpio_mask;
		reg_both &= ~gpio_mask;
		reg_level &= ~gpio_mask;
		break;
	case IRQ_TYPE_EDGE_FALLING:
		reg_type &= ~gpio_mask;
		reg_both &= ~gpio_mask;
		reg_level |= gpio_mask;
		break;
	case IRQ_TYPE_LEVEL_HIGH:
		reg_type |= gpio_mask;
		reg_level &= ~gpio_mask;
		break;
	case IRQ_TYPE_LEVEL_LOW:
		reg_type |= gpio_mask;
		reg_level |= gpio_mask;
		break;
	default:
		return -EINVAL;
	}

	__raw_writel(reg_type, base + GPIO_INT_TYPE);
	__raw_writel(reg_level, base + GPIO_INT_BOTH_EDGE);
	__raw_writel(reg_both, base + GPIO_INT_BOTH_EDGE);

	gpio_ack_irq(irq);

	return 0;
}

static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
{
	unsigned int gpio_irq_no, irq_stat;
	unsigned int port = (unsigned int)get_irq_data(irq);

	irq_stat = __raw_readl(GPIO_BASE(port) + GPIO_INT_STAT);

	gpio_irq_no = GPIO_IRQ_BASE + port * 32;
	for (; irq_stat != 0; irq_stat >>= 1, gpio_irq_no++) {

		if ((irq_stat & 1) == 0)
			continue;

		BUG_ON(!(irq_desc[gpio_irq_no].handle_irq));
		irq_desc[gpio_irq_no].handle_irq(gpio_irq_no,
				&irq_desc[gpio_irq_no]);
	}
}

static struct irq_chip gpio_irq_chip = {
	.name = "GPIO",
	.ack = gpio_ack_irq,
	.mask = gpio_mask_irq,
	.unmask = gpio_unmask_irq,
	.set_type = gpio_set_irq_type,
};

static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset,
				int dir)
{
	unsigned int base = GPIO_BASE(offset / 32);
	unsigned int reg;

	reg = __raw_readl(base + GPIO_DIR);
	if (dir)
		reg |= 1 << (offset % 32);
	else
		reg &= ~(1 << (offset % 32));
	__raw_writel(reg, base + GPIO_DIR);
}

static void gemini_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
	unsigned int base = GPIO_BASE(offset / 32);

	if (value)
		__raw_writel(1 << (offset % 32), base + GPIO_DATA_SET);
	else
		__raw_writel(1 << (offset % 32), base + GPIO_DATA_CLR);
}

static int gemini_gpio_get(struct gpio_chip *chip, unsigned offset)
{
	unsigned int base = GPIO_BASE(offset / 32);

	return (__raw_readl(base + GPIO_DATA_IN) >> (offset % 32)) & 1;
}

static int gemini_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
	_set_gpio_direction(chip, offset, 0);
	return 0;
}

static int gemini_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
					int value)
{
	_set_gpio_direction(chip, offset, 1);
	gemini_gpio_set(chip, offset, value);
	return 0;
}

static struct gpio_chip gemini_gpio_chip = {
	.label			= "Gemini",
	.direction_input	= gemini_gpio_direction_input,
	.get			= gemini_gpio_get,
	.direction_output	= gemini_gpio_direction_output,
	.set			= gemini_gpio_set,
	.base			= 0,
	.ngpio			= GPIO_PORT_NUM * 32,
};

void __init gemini_gpio_init(void)
{
	int i, j;

	for (i = 0; i < GPIO_PORT_NUM; i++) {
		/* disable, unmask and clear all interrupts */
		__raw_writel(0x0, GPIO_BASE(i) + GPIO_INT_EN);
		__raw_writel(0x0, GPIO_BASE(i) + GPIO_INT_MASK);
		__raw_writel(~0x0, GPIO_BASE(i) + GPIO_INT_CLR);

		for (j = GPIO_IRQ_BASE + i * 32;
		     j < GPIO_IRQ_BASE + (i + 1) * 32; j++) {
			set_irq_chip(j, &gpio_irq_chip);
			set_irq_handler(j, handle_edge_irq);
			set_irq_flags(j, IRQF_VALID);
		}

		set_irq_chained_handler(IRQ_GPIO(i), gpio_irq_handler);
		set_irq_data(IRQ_GPIO(i), (void *)i);
	}

	BUG_ON(gpiochip_add(&gemini_gpio_chip));
}
