/*
 * 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 <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/sysdev.h>

#include <mach/hardware.h>
#include <asm/io.h>
#include <asm/setup.h>
#include <asm/mach-types.h>

#include <asm/mach/arch.h>
#include <asm/mach/map.h>

#include "ctrlEnv/mvCtrlEnvLib.h"
#include "boardEnv/mvBoardEnvLib.h"
#include "gpp/mvGpp.h"
#include "mvOs.h"

/*
 * Note: FIQ mask registers are IRQ mask registers + 4 bytes.
 */

unsigned int fiq_int_type[NR_IRQS];

void mv_mask_fiq(unsigned int irq)
{
	if (irq < 32) {
		MV_REG_BIT_RESET(MV_FIQ_MASK_LOW_REG, (1 << irq) );
	} else if(irq < 64) {		/* (irq > 32 && irq < 64) */
		MV_REG_BIT_RESET(MV_FIQ_MASK_HIGH_REG, (1 << (irq - 32)) );
	} else if(irq < 96) {		/* (irq > 64 && irq < 96) */
		MV_REG_BIT_RESET(MV_FIQ_MASK_ERROR_REG, (1 << (irq - 64)) );
	} else if(irq < NR_IRQS) {	/* (irq > 96 && irq < NR_IRQS) */
		MV_U32 bitmask = 1 << (irq & 0x1F);
		MV_U32 reg = (irq - IRQ_GPP_START) >> 5;
		MV_REG_BIT_RESET(MV_GPP_IRQ_MASK_REG(reg), bitmask);
	} else
		printk("mv_mask_fiq: ERR, irq-%u out of scope\n",irq);
}

void mv_unmask_fiq(unsigned int irq)
{
	if (irq < 32) {
		MV_REG_BIT_SET(MV_FIQ_MASK_LOW_REG, (1 << irq) );
	} else if(irq < 64) {		/* (irq > 32 && irq < 64) */
		MV_REG_BIT_SET(MV_FIQ_MASK_HIGH_REG, (1 << (irq - 32)) );
	} else if(irq < 96) {		/* (irq > 64 && irq < 96) */
		MV_REG_BIT_SET(MV_FIQ_MASK_ERROR_REG, (1 << (irq - 64)) );
	} else if(irq < NR_IRQS) {
		MV_U32 bitmask = 1 << (irq & 0x1F);
		MV_U32 reg = (irq - IRQ_GPP_START) >> 5;
		MV_REG_BIT_SET(MV_GPP_IRQ_MASK_REG(reg), bitmask);
		if (fiq_int_type[irq] == GPP_IRQ_TYPE_CHANGE_LEVEL) {
			(MV_REG_READ(MV_GPP_IRQ_POLARITY(reg)) & bitmask)?
				MV_REG_BIT_RESET(MV_GPP_IRQ_POLARITY(reg), bitmask):
				MV_REG_BIT_SET(MV_GPP_IRQ_POLARITY(reg), bitmask);
		}
	} else
		printk("mv_unmask_fiq: ERR, irq-%u out of scope\n",irq);
}

irq_handler_t fiq_handlers[NR_IRQS] = {
	[0 ... NR_IRQS-1] = NULL,
};

static inline int find_fiq_bit(void)
{
	int bit, high_cause_sum_bit;
	MV_U32 mask;
	unsigned long cause;

	/*
	 * Handle Low Cause interrupts
	 */
	cause = MV_REG_READ(MV_IRQ_CAUSE_LOW_REG);

	/* Save High Cause Summary bit to save access to Cause register. */
	high_cause_sum_bit = cause & 0x1;

	cause &= MV_REG_READ(MV_FIQ_MASK_LOW_REG);
	bit = find_first_bit(&cause, 32);
	if (bit < 32)
		goto out;

	/*
	 * Handle High Cause interrupts
	 */
	if (!high_cause_sum_bit)
		goto check_cause_error;
	cause = MV_REG_READ(MV_IRQ_CAUSE_HIGH_REG);
	cause &= MV_REG_READ(MV_FIQ_MASK_HIGH_REG);
	bit = find_first_bit(&cause, 32);
	if (bit >= 32)
		goto check_cause_error;
	if (bit >= 4 && bit <= 15) {
		/* Handle GPIO case */
		bit = (bit - 4) * 8 + IRQ_GPP_START;
		if (bit > IRQ_GPP_START + 88) {
			/* Print some info in the future.
			 * Currently, this case may be traced
			 * only through FIQ exception counter
			 * (cat /proc/fiq_dump).
			 */
			goto err_out;
		}
	} else
		bit += 32;
	goto out;

	/*
	 * Handle Error Cause interrupts
	 */
check_cause_error:
	mask  = MV_REG_READ(MV_FIQ_MASK_ERROR_REG);
	cause = mask & MV_REG_READ(MV_IRQ_CAUSE_ERROR_REG);
	bit = find_first_bit(&cause, 32);
	if (bit < 32)
		goto out;

err_out:
	/* No interrupt found. */
	return -1;

out:
	return bit;
}

typedef void (*fiq_handler_t)(void);
extern fiq_handler_t fiq_userptr;

void handle_all_fiqs(void)
{
	irq_handler_t handler;
	int fiq = find_fiq_bit();

	handler = fiq_handlers[fiq];
	if (handler)
		handler(fiq, NULL);
}

int __must_check
request_fiq(unsigned int irq, irq_handler_t handler, unsigned long flags,
	    const char *name, void *dev)
{
	if ((irq < 0) | (irq >= NR_IRQS))
		return -EINVAL;

	/*
	 * if (flags & IRQF_DISABLED)
	 *	return -EINVAL;
	 */

	mv_mask_fiq(irq);

	if (!fiq_userptr)
		fiq_userptr = handle_all_fiqs;

	if (fiq_handlers[irq])
		return -EINVAL;

	fiq_handlers[irq] = handler;
	mv_unmask_fiq(irq);
	return 0;
}

void free_fiq(unsigned int irq, void *dev_id)
{
	mv_mask_fiq(irq);
	fiq_handlers[irq] = NULL;
}



