/*
 * Interrupt controller driver for PowerPC 4xx-based processors.
 *
 * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
 * Copyright (c) 2004, 2005 Zultys Technologies
 *
 * Based on original code by
 *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
 *    Armin Custer <akuster@mvista.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.
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/stddef.h>

#include <asm/processor.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/ppc4xx_pic.h>
#include <asm/machdep.h>

/* See comment in include/arch-ppc/ppc4xx_pic.h
 * for more info about these two variables
 */
extern struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[NR_UICS]
    __attribute__ ((weak));
extern unsigned char ppc4xx_uic_ext_irq_cfg[] __attribute__ ((weak));

#define IRQ_MASK_UIC0(irq)		(1 << (31 - (irq)))
#define IRQ_MASK_UICx(irq)		(1 << (31 - ((irq) & 0x1f)))
#define IRQ_MASK_UIC1(irq)		IRQ_MASK_UICx(irq)
#define IRQ_MASK_UIC2(irq)		IRQ_MASK_UICx(irq)
#define IRQ_MASK_UIC3(irq)		IRQ_MASK_UICx(irq)

#define UIC_HANDLERS(n)							\
static void ppc4xx_uic##n##_enable(unsigned int irq)			\
{									\
	u32 mask = IRQ_MASK_UIC##n(irq);				\
	if (irq_desc[irq].status & IRQ_LEVEL)				\
		mtdcr(DCRN_UIC_SR(UIC##n), mask);			\
	ppc_cached_irq_mask[n] |= mask;					\
	mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]);		\
}									\
									\
static void ppc4xx_uic##n##_disable(unsigned int irq)			\
{									\
	ppc_cached_irq_mask[n] &= ~IRQ_MASK_UIC##n(irq);		\
	mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]);		\
	ACK_UIC##n##_PARENT						\
}									\
									\
static void ppc4xx_uic##n##_ack(unsigned int irq)			\
{									\
	u32 mask = IRQ_MASK_UIC##n(irq);				\
	ppc_cached_irq_mask[n] &= ~mask;				\
	mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]);		\
	mtdcr(DCRN_UIC_SR(UIC##n), mask);				\
	ACK_UIC##n##_PARENT						\
}									\
									\
static void ppc4xx_uic##n##_end(unsigned int irq)			\
{									\
	unsigned int status = irq_desc[irq].status;			\
	u32 mask = IRQ_MASK_UIC##n(irq);				\
	if (status & IRQ_LEVEL) {					\
		mtdcr(DCRN_UIC_SR(UIC##n), mask);			\
		ACK_UIC##n##_PARENT					\
	}								\
	if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {		\
		ppc_cached_irq_mask[n] |= mask;				\
		mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]);	\
	}								\
}

#define DECLARE_UIC(n)							\
{									\
	.typename 	= "UIC"#n,					\
	.enable 	= ppc4xx_uic##n##_enable,			\
	.disable 	= ppc4xx_uic##n##_disable,			\
	.ack 		= ppc4xx_uic##n##_ack,				\
	.end 		= ppc4xx_uic##n##_end,				\
}									\

#if NR_UICS == 4
#define ACK_UIC0_PARENT
#define ACK_UIC1_PARENT	mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC);
#define ACK_UIC2_PARENT	mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC2NC);
#define ACK_UIC3_PARENT	mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC3NC);
UIC_HANDLERS(0);
UIC_HANDLERS(1);
UIC_HANDLERS(2);
UIC_HANDLERS(3);

static int ppc4xx_pic_get_irq(struct pt_regs *regs)
{
	u32 uic0 = mfdcr(DCRN_UIC_MSR(UIC0));
	if (uic0 & UIC0_UIC1NC)
		return 64 - ffs(mfdcr(DCRN_UIC_MSR(UIC1)));
	else if (uic0 & UIC0_UIC2NC)
		return 96 - ffs(mfdcr(DCRN_UIC_MSR(UIC2)));
	else if (uic0 & UIC0_UIC3NC)
		return 128 - ffs(mfdcr(DCRN_UIC_MSR(UIC3)));
	else
		return uic0 ? 32 - ffs(uic0) : -1;
}

static void __init ppc4xx_pic_impl_init(void)
{
	/* Enable cascade interrupts in UIC0 */
	ppc_cached_irq_mask[0] |= UIC0_UIC1NC | UIC0_UIC2NC | UIC0_UIC3NC;
	mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC | UIC0_UIC2NC | UIC0_UIC3NC);
	mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[0]);
}

#elif NR_UICS == 3
#define ACK_UIC0_PARENT	mtdcr(DCRN_UIC_SR(UICB), UICB_UIC0NC);
#define ACK_UIC1_PARENT	mtdcr(DCRN_UIC_SR(UICB), UICB_UIC1NC);
#define ACK_UIC2_PARENT	mtdcr(DCRN_UIC_SR(UICB), UICB_UIC2NC);
UIC_HANDLERS(0);
UIC_HANDLERS(1);
UIC_HANDLERS(2);

static int ppc4xx_pic_get_irq(struct pt_regs *regs)
{
	u32 uicb = mfdcr(DCRN_UIC_MSR(UICB));
	if (uicb & UICB_UIC0NC)
		return 32 - ffs(mfdcr(DCRN_UIC_MSR(UIC0)));
	else if (uicb & UICB_UIC1NC)
		return 64 - ffs(mfdcr(DCRN_UIC_MSR(UIC1)));
	else if (uicb & UICB_UIC2NC)
		return 96 - ffs(mfdcr(DCRN_UIC_MSR(UIC2)));
	else
		return -1;
}

static void __init ppc4xx_pic_impl_init(void)
{
#if defined(CONFIG_440GX)
	/* Disable 440GP compatibility mode if it was enabled in firmware */
	SDR_WRITE(DCRN_SDR_MFR, SDR_READ(DCRN_SDR_MFR) & ~DCRN_SDR_MFR_PCM);
#endif
	/* Configure Base UIC */
	mtdcr(DCRN_UIC_CR(UICB), 0);
	mtdcr(DCRN_UIC_TR(UICB), 0);
	mtdcr(DCRN_UIC_PR(UICB), 0xffffffff);
	mtdcr(DCRN_UIC_SR(UICB), 0xffffffff);
	mtdcr(DCRN_UIC_ER(UICB), UICB_UIC0NC | UICB_UIC1NC | UICB_UIC2NC);
}

#elif NR_UICS == 2
#define ACK_UIC0_PARENT
#define ACK_UIC1_PARENT	mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC);
UIC_HANDLERS(0);
UIC_HANDLERS(1);

static int ppc4xx_pic_get_irq(struct pt_regs *regs)
{
	u32 uic0 = mfdcr(DCRN_UIC_MSR(UIC0));
	if (uic0 & UIC0_UIC1NC)
		return 64 - ffs(mfdcr(DCRN_UIC_MSR(UIC1)));
	else
		return uic0 ? 32 - ffs(uic0) : -1;
}

static void __init ppc4xx_pic_impl_init(void)
{
	/* Enable cascade interrupt in UIC0 */
	ppc_cached_irq_mask[0] |= UIC0_UIC1NC;
	mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC);
	mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[0]);
}

#elif NR_UICS == 1
#define ACK_UIC0_PARENT
UIC_HANDLERS(0);

static int ppc4xx_pic_get_irq(struct pt_regs *regs)
{
	u32 uic0 = mfdcr(DCRN_UIC_MSR(UIC0));
	return uic0 ? 32 - ffs(uic0) : -1;
}

static inline void ppc4xx_pic_impl_init(void)
{
}
#endif

static struct ppc4xx_uic_impl {
	struct hw_interrupt_type decl;
	int base;			/* Base DCR number */
} __uic[] = {
	{ .decl = DECLARE_UIC(0), .base = UIC0 },
#if NR_UICS > 1
	{ .decl = DECLARE_UIC(1), .base = UIC1 },
#if NR_UICS > 2
	{ .decl = DECLARE_UIC(2), .base = UIC2 },
#if NR_UICS > 3
	{ .decl = DECLARE_UIC(3), .base = UIC3 },
#endif
#endif
#endif
};

static inline int is_level_sensitive(int irq)
{
	u32 tr = mfdcr(DCRN_UIC_TR(__uic[irq >> 5].base));
	return (tr & IRQ_MASK_UICx(irq)) == 0;
}

void __init ppc4xx_pic_init(void)
{
	int i;
	unsigned char *eirqs = ppc4xx_uic_ext_irq_cfg;

	for (i = 0; i < NR_UICS; ++i) {
		int base = __uic[i].base;

		/* Disable everything by default */
		ppc_cached_irq_mask[i] = 0;
		mtdcr(DCRN_UIC_ER(base), 0);

		/* We don't use critical interrupts */
		mtdcr(DCRN_UIC_CR(base), 0);

		/* Configure polarity and triggering */
		if (ppc4xx_core_uic_cfg) {
			struct ppc4xx_uic_settings *p = ppc4xx_core_uic_cfg + i;
			u32 mask = p->ext_irq_mask;
			u32 pr = mfdcr(DCRN_UIC_PR(base)) & mask;
			u32 tr = mfdcr(DCRN_UIC_TR(base)) & mask;

			/* "Fixed" interrupts (on-chip devices) */
			pr |= p->polarity & ~mask;
			tr |= p->triggering & ~mask;

			/* Merge external IRQs settings if board port
			 * provided them
			 */
			if (eirqs && mask) {
				pr &= ~mask;
				tr &= ~mask;
				while (mask) {
					/* Extract current external IRQ mask */
					u32 eirq_mask = 1 << __ilog2(mask);

					if (!(*eirqs & IRQ_SENSE_LEVEL))
						tr |= eirq_mask;

					if (*eirqs & IRQ_POLARITY_POSITIVE)
						pr |= eirq_mask;

					mask &= ~eirq_mask;
					++eirqs;
				}
			}
			mtdcr(DCRN_UIC_PR(base), pr);
			mtdcr(DCRN_UIC_TR(base), tr);
		}

		/* ACK any pending interrupts to prevent false
		 * triggering after first enable
		 */
		mtdcr(DCRN_UIC_SR(base), 0xffffffff);
	}

	/* Perform optional implementation specific setup
	 * (e.g. enable cascade interrupts for multi-UIC configurations)
	 */
	ppc4xx_pic_impl_init();

	/* Attach low-level handlers */
	for (i = 0; i < (NR_UICS << 5); ++i) {
		irq_desc[i].handler = &__uic[i >> 5].decl;
		if (is_level_sensitive(i))
			irq_desc[i].status |= IRQ_LEVEL;
	}

	ppc_md.get_irq = ppc4xx_pic_get_irq;
}
