// SPDX-License-Identifier: GPL-2.0+
/*
 * (C) Copyright 2007 Michal Simek
 * (C) Copyright 2004 Atmark Techno, Inc.
 *
 * Michal  SIMEK <monstr@monstr.eu>
 * Yasushi SHOJI <yashi@atmark-techno.com>
 */

#include <common.h>
#include <command.h>
#include <fdtdec.h>
#include <irq_func.h>
#include <log.h>
#include <malloc.h>
#include <asm/microblaze_intc.h>
#include <asm/asm.h>

DECLARE_GLOBAL_DATA_PTR;

void enable_interrupts(void)
{
	debug("Enable interrupts for the whole CPU\n");
	MSRSET(0x2);
}

int disable_interrupts(void)
{
	unsigned int msr;

	MFS(msr, rmsr);
	MSRCLR(0x2);
	return (msr & 0x2) != 0;
}

static struct irq_action *vecs;
static u32 irq_no;

/* mapping structure to interrupt controller */
microblaze_intc_t *intc;

/* default handler */
static void def_hdlr(void)
{
	puts("def_hdlr\n");
}

static void enable_one_interrupt(int irq)
{
	int mask;
	int offset = 1;

	offset <<= irq;
	mask = intc->ier;
	intc->ier = (mask | offset);

	debug("Enable one interrupt irq %x - mask %x,ier %x\n", offset, mask,
	      intc->ier);
	debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
	      intc->iar, intc->mer);
}

static void disable_one_interrupt(int irq)
{
	int mask;
	int offset = 1;

	offset <<= irq;
	mask = intc->ier;
	intc->ier = (mask & ~offset);

	debug("Disable one interrupt irq %x - mask %x,ier %x\n", irq, mask,
	      intc->ier);
	debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
	      intc->iar, intc->mer);
}

int install_interrupt_handler(int irq, interrupt_handler_t *hdlr, void *arg)
{
	struct irq_action *act;

	/* irq out of range */
	if ((irq < 0) || (irq > irq_no)) {
		puts("IRQ out of range\n");
		return -1;
	}
	act = &vecs[irq];
	if (hdlr) {		/* enable */
		act->handler = hdlr;
		act->arg = arg;
		act->count = 0;
		enable_one_interrupt(irq);
		return 0;
	}

	/* Disable */
	act->handler = (interrupt_handler_t *)def_hdlr;
	act->arg = (void *)irq;
	disable_one_interrupt(irq);
	return 1;
}

/* initialization interrupt controller - hardware */
static void intc_init(void)
{
	intc->mer = 0;
	intc->ier = 0;
	intc->iar = 0xFFFFFFFF;
	/* XIntc_Start - hw_interrupt enable and all interrupt enable */
	intc->mer = 0x3;

	debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
	      intc->iar, intc->mer);
}

int interrupt_init(void)
{
	int i;
	const void *blob = gd->fdt_blob;
	int node = 0;

	debug("INTC: Initialization\n");

	node = fdt_node_offset_by_compatible(blob, node,
				"xlnx,xps-intc-1.00.a");
	if (node != -1) {
		fdt_addr_t base = fdtdec_get_addr(blob, node, "reg");
		if (base == FDT_ADDR_T_NONE)
			return -1;

		debug("INTC: Base addr %lx\n", base);
		intc = (microblaze_intc_t *)base;
		irq_no = fdtdec_get_int(blob, node, "xlnx,num-intr-inputs", 0);
		debug("INTC: IRQ NO %x\n", irq_no);
	} else {
		return node;
	}

	if (irq_no) {
		vecs = calloc(1, sizeof(struct irq_action) * irq_no);
		if (vecs == NULL) {
			puts("Interrupt vector allocation failed\n");
			return -1;
		}

		/* initialize irq list */
		for (i = 0; i < irq_no; i++) {
			vecs[i].handler = (interrupt_handler_t *)def_hdlr;
			vecs[i].arg = (void *)i;
			vecs[i].count = 0;
		}
		/* initialize intc controller */
		intc_init();
		enable_interrupts();
	} else {
		puts("Undefined interrupt controller\n");
	}
	return 0;
}

void interrupt_handler(void)
{
	int irqs = intc->ivr;	/* find active interrupt */
	int mask = 1;
	int value;
	struct irq_action *act = vecs + irqs;

	debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
	      intc->iar, intc->mer);
#ifdef DEBUG
	R14(value);
#endif
	debug("Interrupt handler on %x line, r14 %x\n", irqs, value);

	debug("Jumping to interrupt handler rutine addr %x,count %x,arg %x\n",
	      (u32)act->handler, act->count, (u32)act->arg);
	act->handler(act->arg);
	act->count++;

	intc->iar = mask << irqs;

	debug("Dump INTC reg, isr %x, ier %x, iar %x, mer %x\n", intc->isr,
	      intc->ier, intc->iar, intc->mer);
#ifdef DEBUG
	R14(value);
#endif
	debug("Interrupt handler on %x line, r14 %x\n", irqs, value);
}

#if defined(CONFIG_CMD_IRQ)
int do_irqinfo(struct cmd_tbl *cmdtp, int flag, int argc, const char *argv[])
{
	int i;
	struct irq_action *act = vecs;

	if (irq_no) {
		puts("\nInterrupt-Information:\n\n"
		      "Nr  Routine   Arg       Count\n"
		      "-----------------------------\n");

		for (i = 0; i < irq_no; i++) {
			if (act->handler != (interrupt_handler_t *)def_hdlr) {
				printf("%02d  %08x  %08x  %d\n", i,
				       (int)act->handler, (int)act->arg,
				       act->count);
			}
			act++;
		}
		puts("\n");
	} else {
		puts("Undefined interrupt controller\n");
	}
	return 0;
}
#endif
