/*
 * linux/arch/arm/mach-msm/gpio.c
 *
 * Copyright (C) 2005 HP Labs
 * Copyright (C) 2008 Google, Inc.
 * Copyright (C) 2009 Pavel Machek <pavel@ucw.cz>
 *
 * 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/module.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>

#include "board-trout.h"

static uint8_t trout_int_mask[2] = {
	[0] = 0xff, /* mask all interrupts */
	[1] = 0xff,
};
static uint8_t trout_sleep_int_mask[] = {
	[0] = 0xff,
	[1] = 0xff,
};

struct msm_gpio_chip {
	struct gpio_chip	chip;
	void __iomem		*reg;	/* Base of register bank */
	u8			shadow;
};

#define to_msm_gpio_chip(c) container_of(c, struct msm_gpio_chip, chip)

static int msm_gpiolib_get(struct gpio_chip *chip, unsigned offset)
{
	struct msm_gpio_chip *msm_gpio = to_msm_gpio_chip(chip);
	unsigned mask = 1 << offset;

	return !!(readb(msm_gpio->reg) & mask);
}

static void msm_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val)
{
	struct msm_gpio_chip *msm_gpio = to_msm_gpio_chip(chip);
	unsigned mask = 1 << offset;

	if (val)
		msm_gpio->shadow |= mask;
	else
		msm_gpio->shadow &= ~mask;

	writeb(msm_gpio->shadow, msm_gpio->reg);
}

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

static int msm_gpiolib_direction_output(struct gpio_chip *chip,
					 unsigned offset, int val)
{
	msm_gpiolib_set(chip, offset, val);
	return 0;
}

static int trout_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
	return TROUT_GPIO_TO_INT(offset + chip->base);
}

#define TROUT_GPIO_BANK(name, reg_num, base_gpio, shadow_val)		\
	{								\
		.chip = {						\
			.label		  = name,			\
			.direction_input  = msm_gpiolib_direction_input,\
			.direction_output = msm_gpiolib_direction_output, \
			.get		  = msm_gpiolib_get,		\
			.set		  = msm_gpiolib_set,		\
			.to_irq		  = trout_gpio_to_irq,		\
			.base		  = base_gpio,			\
			.ngpio		  = 8,				\
		},							\
		.reg = reg_num + TROUT_CPLD_BASE,			\
		.shadow = shadow_val,					\
	}

static struct msm_gpio_chip msm_gpio_banks[] = {
#if defined(CONFIG_MSM_DEBUG_UART1)
	/* H2W pins <-> UART1 */
	TROUT_GPIO_BANK("MISC2", 0x00,   TROUT_GPIO_MISC2_BASE, 0x40),
#else
	/* H2W pins <-> UART3, Bluetooth <-> UART1 */
	TROUT_GPIO_BANK("MISC2", 0x00,   TROUT_GPIO_MISC2_BASE, 0x80),
#endif
	/* I2C pull */
	TROUT_GPIO_BANK("MISC3", 0x02,   TROUT_GPIO_MISC3_BASE, 0x04),
	TROUT_GPIO_BANK("MISC4", 0x04,   TROUT_GPIO_MISC4_BASE, 0),
	/* mmdi 32k en */
	TROUT_GPIO_BANK("MISC5", 0x06,   TROUT_GPIO_MISC5_BASE, 0x04),
	TROUT_GPIO_BANK("INT2", 0x08,    TROUT_GPIO_INT2_BASE,  0),
	TROUT_GPIO_BANK("MISC1", 0x0a,   TROUT_GPIO_MISC1_BASE, 0),
	TROUT_GPIO_BANK("VIRTUAL", 0x12, TROUT_GPIO_VIRTUAL_BASE, 0),
};

static void trout_gpio_irq_ack(struct irq_data *d)
{
	int bank = TROUT_INT_TO_BANK(d->irq);
	uint8_t mask = TROUT_INT_TO_MASK(d->irq);
	int reg = TROUT_BANK_TO_STAT_REG(bank);
	/*printk(KERN_INFO "trout_gpio_irq_ack irq %d\n", d->irq);*/
	writeb(mask, TROUT_CPLD_BASE + reg);
}

static void trout_gpio_irq_mask(struct irq_data *d)
{
	unsigned long flags;
	uint8_t reg_val;
	int bank = TROUT_INT_TO_BANK(d->irq);
	uint8_t mask = TROUT_INT_TO_MASK(d->irq);
	int reg = TROUT_BANK_TO_MASK_REG(bank);

	local_irq_save(flags);
	reg_val = trout_int_mask[bank] |= mask;
	/*printk(KERN_INFO "trout_gpio_irq_mask irq %d => %d:%02x\n",
	       d->irq, bank, reg_val);*/
	writeb(reg_val, TROUT_CPLD_BASE + reg);
	local_irq_restore(flags);
}

static void trout_gpio_irq_unmask(struct irq_data *d)
{
	unsigned long flags;
	uint8_t reg_val;
	int bank = TROUT_INT_TO_BANK(d->irq);
	uint8_t mask = TROUT_INT_TO_MASK(d->irq);
	int reg = TROUT_BANK_TO_MASK_REG(bank);

	local_irq_save(flags);
	reg_val = trout_int_mask[bank] &= ~mask;
	/*printk(KERN_INFO "trout_gpio_irq_unmask irq %d => %d:%02x\n",
	       d->irq, bank, reg_val);*/
	writeb(reg_val, TROUT_CPLD_BASE + reg);
	local_irq_restore(flags);
}

int trout_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
{
	unsigned long flags;
	int bank = TROUT_INT_TO_BANK(d->irq);
	uint8_t mask = TROUT_INT_TO_MASK(d->irq);

	local_irq_save(flags);
	if(on)
		trout_sleep_int_mask[bank] &= ~mask;
	else
		trout_sleep_int_mask[bank] |= mask;
	local_irq_restore(flags);
	return 0;
}

static void trout_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
{
	int j, m;
	unsigned v;
	int bank;
	int stat_reg;
	int int_base = TROUT_INT_START;
	uint8_t int_mask;

	for (bank = 0; bank < 2; bank++) {
		stat_reg = TROUT_BANK_TO_STAT_REG(bank);
		v = readb(TROUT_CPLD_BASE + stat_reg);
		int_mask = trout_int_mask[bank];
		if (v & int_mask) {
			writeb(v & int_mask, TROUT_CPLD_BASE + stat_reg);
			printk(KERN_ERR "trout_gpio_irq_handler: got masked "
			       "interrupt: %d:%02x\n", bank, v & int_mask);
		}
		v &= ~int_mask;
		while (v) {
			m = v & -v;
			j = fls(m) - 1;
			/*printk(KERN_INFO "msm_gpio_irq_handler %d:%02x %02x b"
			       "it %d irq %d\n", bank, v, m, j, int_base + j);*/
			v &= ~m;
			generic_handle_irq(int_base + j);
		}
		int_base += TROUT_INT_BANK0_COUNT;
	}
	desc->irq_data.chip->irq_ack(&desc->irq_data);
}

static struct irq_chip trout_gpio_irq_chip = {
	.name          = "troutgpio",
	.irq_ack       = trout_gpio_irq_ack,
	.irq_mask      = trout_gpio_irq_mask,
	.irq_unmask    = trout_gpio_irq_unmask,
	.irq_set_wake  = trout_gpio_irq_set_wake,
};

/*
 * Called from the processor-specific init to enable GPIO pin support.
 */
int __init trout_init_gpio(void)
{
	int i;
	for(i = TROUT_INT_START; i <= TROUT_INT_END; i++) {
		irq_set_chip_and_handler(i, &trout_gpio_irq_chip,
					 handle_edge_irq);
		set_irq_flags(i, IRQF_VALID);
	}

	for (i = 0; i < ARRAY_SIZE(msm_gpio_banks); i++)
		gpiochip_add(&msm_gpio_banks[i].chip);

	irq_set_irq_type(MSM_GPIO_TO_INT(17), IRQF_TRIGGER_HIGH);
	irq_set_chained_handler(MSM_GPIO_TO_INT(17), trout_gpio_irq_handler);
	irq_set_irq_wake(MSM_GPIO_TO_INT(17), 1);

	return 0;
}

postcore_initcall(trout_init_gpio);

