/*
 * 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/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(void)
{
	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(void)
{
	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(void)
{
	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(void)
{
	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].chip = &__uic[i >> 5].decl;
		if (is_level_sensitive(i))
			irq_desc[i].status |= IRQ_LEVEL;
	}

	ppc_md.get_irq = ppc4xx_pic_get_irq;
}
