/*
 * s6000 gpio driver
 *
 * Copyright (c) 2009 emlix GmbH
 * Authors:	Oskar Schirmer <oskar@scara.com>
 *		Johannes Weiner <hannes@cmpxchg.org>
 *		Daniel Gloeckner <dg@emlix.com>
 */
#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/gpio.h>

#include <variant/hardware.h>

#define IRQ_BASE XTENSA_NR_IRQS

#define S6_GPIO_DATA		0x000
#define S6_GPIO_IS		0x404
#define S6_GPIO_IBE		0x408
#define S6_GPIO_IEV		0x40C
#define S6_GPIO_IE		0x410
#define S6_GPIO_RIS		0x414
#define S6_GPIO_MIS		0x418
#define S6_GPIO_IC		0x41C
#define S6_GPIO_AFSEL		0x420
#define S6_GPIO_DIR		0x800
#define S6_GPIO_BANK(nr)	((nr) * 0x1000)
#define S6_GPIO_MASK(nr)	(4 << (nr))
#define S6_GPIO_OFFSET(nr) \
		(S6_GPIO_BANK((nr) >> 3) + S6_GPIO_MASK((nr) & 7))

static int direction_input(struct gpio_chip *chip, unsigned int off)
{
	writeb(0, S6_REG_GPIO + S6_GPIO_DIR + S6_GPIO_OFFSET(off));
	return 0;
}

static int get(struct gpio_chip *chip, unsigned int off)
{
	return readb(S6_REG_GPIO + S6_GPIO_DATA + S6_GPIO_OFFSET(off));
}

static int direction_output(struct gpio_chip *chip, unsigned int off, int val)
{
	unsigned rel = S6_GPIO_OFFSET(off);
	writeb(~0, S6_REG_GPIO + S6_GPIO_DIR + rel);
	writeb(val ? ~0 : 0, S6_REG_GPIO + S6_GPIO_DATA + rel);
	return 0;
}

static void set(struct gpio_chip *chip, unsigned int off, int val)
{
	writeb(val ? ~0 : 0, S6_REG_GPIO + S6_GPIO_DATA + S6_GPIO_OFFSET(off));
}

static int to_irq(struct gpio_chip *chip, unsigned offset)
{
	if (offset < 8)
		return offset + IRQ_BASE;
	return -EINVAL;
}

static struct gpio_chip gpiochip = {
	.owner = THIS_MODULE,
	.direction_input = direction_input,
	.get = get,
	.direction_output = direction_output,
	.set = set,
	.to_irq = to_irq,
	.base = 0,
	.ngpio = 24,
	.can_sleep = 0, /* no blocking io needed */
	.exported = 0, /* no exporting to userspace */
};

int s6_gpio_init(u32 afsel)
{
	writeb(afsel, S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_AFSEL);
	writeb(afsel >> 8, S6_REG_GPIO + S6_GPIO_BANK(1) + S6_GPIO_AFSEL);
	writeb(afsel >> 16, S6_REG_GPIO + S6_GPIO_BANK(2) + S6_GPIO_AFSEL);
	return gpiochip_add(&gpiochip);
}

static void ack(struct irq_data *d)
{
	writeb(1 << (d->irq - IRQ_BASE), S6_REG_GPIO + S6_GPIO_IC);
}

static void mask(struct irq_data *d)
{
	u8 r = readb(S6_REG_GPIO + S6_GPIO_IE);
	r &= ~(1 << (d->irq - IRQ_BASE));
	writeb(r, S6_REG_GPIO + S6_GPIO_IE);
}

static void unmask(struct irq_data *d)
{
	u8 m = readb(S6_REG_GPIO + S6_GPIO_IE);
	m |= 1 << (d->irq - IRQ_BASE);
	writeb(m, S6_REG_GPIO + S6_GPIO_IE);
}

static int set_type(struct irq_data *d, unsigned int type)
{
	const u8 m = 1 << (d->irq - IRQ_BASE);
	irq_flow_handler_t handler;
	u8 reg;

	if (type == IRQ_TYPE_PROBE) {
		if ((readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_AFSEL) & m)
		    || (readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IE) & m)
		    || readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_DIR
			      + S6_GPIO_MASK(irq - IRQ_BASE)))
			return 0;
		type = IRQ_TYPE_EDGE_BOTH;
	}

	reg = readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IS);
	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) {
		reg |= m;
		handler = handle_level_irq;
	} else {
		reg &= ~m;
		handler = handle_edge_irq;
	}
	writeb(reg, S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IS);
	__irq_set_handler_locked(irq, handler);

	reg = readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IEV);
	if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_EDGE_RISING))
		reg |= m;
	else
		reg &= ~m;
	writeb(reg, S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IEV);

	reg = readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IBE);
	if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
		reg |= m;
	else
		reg &= ~m;
	writeb(reg, S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IBE);
	return 0;
}

static struct irq_chip gpioirqs = {
	.name = "GPIO",
	.irq_ack = ack,
	.irq_mask = mask,
	.irq_unmask = unmask,
	.irq_set_type = set_type,
};

static u8 demux_masks[4];

static void demux_irqs(unsigned int irq, struct irq_desc *desc)
{
	struct irq_chip *chip = irq_desc_get_chip(desc);
	u8 *mask = irq_desc_get_handler_data(desc);
	u8 pending;
	int cirq;

	chip->irq_mask(&desc->irq_data);
	chip->irq_ack(&desc->irq_data);
	pending = readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_MIS) & *mask;
	cirq = IRQ_BASE - 1;
	while (pending) {
		int n = ffs(pending);
		cirq += n;
		pending >>= n;
		generic_handle_irq(cirq);
	}
	chip->irq_unmask(&desc->irq_data);
}

extern const signed char *platform_irq_mappings[XTENSA_NR_IRQS];

void __init variant_init_irq(void)
{
	int irq, n;
	writeb(0, S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IE);
	for (irq = n = 0; irq < XTENSA_NR_IRQS; irq++) {
		const signed char *mapping = platform_irq_mappings[irq];
		int alone = 1;
		u8 mask;
		if (!mapping)
			continue;
		for(mask = 0; *mapping != -1; mapping++)
			switch (*mapping) {
			case S6_INTC_GPIO(0):
				mask |= 1 << 0;
				break;
			case S6_INTC_GPIO(1):
				mask |= 1 << 1;
				break;
			case S6_INTC_GPIO(2):
				mask |= 1 << 2;
				break;
			case S6_INTC_GPIO(3):
				mask |= 0x1f << 3;
				break;
			default:
				alone = 0;
			}
		if (mask) {
			int cirq, i;
			if (!alone) {
				printk(KERN_ERR "chained irq chips can't share"
					" parent irq %i\n", irq);
				continue;
			}
			demux_masks[n] = mask;
			cirq = IRQ_BASE - 1;
			do {
				i = ffs(mask);
				cirq += i;
				mask >>= i;
				irq_set_chip(cirq, &gpioirqs);
				irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW);
			} while (mask);
			irq_set_handler_data(irq, demux_masks + n);
			irq_set_chained_handler(irq, demux_irqs);
			if (++n == ARRAY_SIZE(demux_masks))
				break;
		}
	}
}
