/*
 * This file implements an irqchip for OPAL events. Whenever there is
 * an interrupt that is handled by OPAL we get passed a list of events
 * that Linux needs to do something about. These basically look like
 * interrupts to Linux so we implement an irqchip to handle them.
 *
 * Copyright Alistair Popple, IBM Corporation 2014.
 *
 * 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/bitops.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/irqdomain.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/slab.h>

#include <asm/machdep.h>
#include <asm/opal.h>

#include "powernv.h"

/* Maximum number of events supported by OPAL firmware */
#define MAX_NUM_EVENTS 64

struct opal_event_irqchip {
	struct irq_chip irqchip;
	struct irq_domain *domain;
	unsigned long mask;
};
static struct opal_event_irqchip opal_event_irqchip;
static u64 last_outstanding_events;
static unsigned int opal_irq_count;
static unsigned int *opal_irqs;

void opal_handle_events(void)
{
	__be64 events = 0;
	u64 e;

	e = READ_ONCE(last_outstanding_events) & opal_event_irqchip.mask;
again:
	while (e) {
		int virq, hwirq;

		hwirq = fls64(e) - 1;
		e &= ~BIT_ULL(hwirq);

		local_irq_disable();
		virq = irq_find_mapping(opal_event_irqchip.domain, hwirq);
		if (virq) {
			irq_enter();
			generic_handle_irq(virq);
			irq_exit();
		}
		local_irq_enable();

		cond_resched();
	}
	last_outstanding_events = 0;
	if (opal_poll_events(&events) != OPAL_SUCCESS)
		return;
	e = be64_to_cpu(events) & opal_event_irqchip.mask;
	if (e)
		goto again;
}

bool opal_have_pending_events(void)
{
	if (last_outstanding_events & opal_event_irqchip.mask)
		return true;
	return false;
}

static void opal_event_mask(struct irq_data *d)
{
	clear_bit(d->hwirq, &opal_event_irqchip.mask);
}

static void opal_event_unmask(struct irq_data *d)
{
	set_bit(d->hwirq, &opal_event_irqchip.mask);
	if (opal_have_pending_events())
		opal_wake_poller();
}

static int opal_event_set_type(struct irq_data *d, unsigned int flow_type)
{
	/*
	 * For now we only support level triggered events. The irq
	 * handler will be called continuously until the event has
	 * been cleared in OPAL.
	 */
	if (flow_type != IRQ_TYPE_LEVEL_HIGH)
		return -EINVAL;

	return 0;
}

static struct opal_event_irqchip opal_event_irqchip = {
	.irqchip = {
		.name = "OPAL EVT",
		.irq_mask = opal_event_mask,
		.irq_unmask = opal_event_unmask,
		.irq_set_type = opal_event_set_type,
	},
	.mask = 0,
};

static int opal_event_map(struct irq_domain *d, unsigned int irq,
			irq_hw_number_t hwirq)
{
	irq_set_chip_data(irq, &opal_event_irqchip);
	irq_set_chip_and_handler(irq, &opal_event_irqchip.irqchip,
				handle_level_irq);

	return 0;
}

static irqreturn_t opal_interrupt(int irq, void *data)
{
	__be64 events;

	opal_handle_interrupt(virq_to_hw(irq), &events);
	last_outstanding_events = be64_to_cpu(events);
	if (opal_have_pending_events())
		opal_wake_poller();

	return IRQ_HANDLED;
}

static int opal_event_match(struct irq_domain *h, struct device_node *node,
			    enum irq_domain_bus_token bus_token)
{
	return irq_domain_get_of_node(h) == node;
}

static int opal_event_xlate(struct irq_domain *h, struct device_node *np,
			   const u32 *intspec, unsigned int intsize,
			   irq_hw_number_t *out_hwirq, unsigned int *out_flags)
{
	*out_hwirq = intspec[0];
	*out_flags = IRQ_TYPE_LEVEL_HIGH;

	return 0;
}

static const struct irq_domain_ops opal_event_domain_ops = {
	.match	= opal_event_match,
	.map	= opal_event_map,
	.xlate	= opal_event_xlate,
};

void opal_event_shutdown(void)
{
	unsigned int i;

	/* First free interrupts, which will also mask them */
	for (i = 0; i < opal_irq_count; i++) {
		if (!opal_irqs[i])
			continue;

		if (in_interrupt() || irqs_disabled())
			disable_irq_nosync(opal_irqs[i]);
		else
			free_irq(opal_irqs[i], NULL);

		opal_irqs[i] = 0;
	}
}

int __init opal_event_init(void)
{
	struct device_node *dn, *opal_node;
	const char **names;
	u32 *irqs;
	int i, rc;

	opal_node = of_find_node_by_path("/ibm,opal");
	if (!opal_node) {
		pr_warn("opal: Node not found\n");
		return -ENODEV;
	}

	/* If dn is NULL it means the domain won't be linked to a DT
	 * node so therefore irq_of_parse_and_map(...) wont work. But
	 * that shouldn't be problem because if we're running a
	 * version of skiboot that doesn't have the dn then the
	 * devices won't have the correct properties and will have to
	 * fall back to the legacy method (opal_event_request(...))
	 * anyway. */
	dn = of_find_compatible_node(NULL, NULL, "ibm,opal-event");
	opal_event_irqchip.domain = irq_domain_add_linear(dn, MAX_NUM_EVENTS,
				&opal_event_domain_ops, &opal_event_irqchip);
	of_node_put(dn);
	if (!opal_event_irqchip.domain) {
		pr_warn("opal: Unable to create irq domain\n");
		rc = -ENOMEM;
		goto out;
	}

	/* Get opal-interrupts property and names if present */
	rc = of_property_count_u32_elems(opal_node, "opal-interrupts");
	if (rc < 0)
		goto out;

	opal_irq_count = rc;
	pr_debug("Found %d interrupts reserved for OPAL\n", opal_irq_count);

	irqs = kcalloc(opal_irq_count, sizeof(*irqs), GFP_KERNEL);
	names = kcalloc(opal_irq_count, sizeof(*names), GFP_KERNEL);
	opal_irqs = kcalloc(opal_irq_count, sizeof(*opal_irqs), GFP_KERNEL);

	if (WARN_ON(!irqs || !names || !opal_irqs))
		goto out_free;

	rc = of_property_read_u32_array(opal_node, "opal-interrupts",
					irqs, opal_irq_count);
	if (rc < 0) {
		pr_err("Error %d reading opal-interrupts array\n", rc);
		goto out_free;
	}

	/* It's not an error for the names to be missing */
	of_property_read_string_array(opal_node, "opal-interrupts-names",
				      names, opal_irq_count);

	/* Install interrupt handlers */
	for (i = 0; i < opal_irq_count; i++) {
		unsigned int virq;
		char *name;

		/* Get hardware and virtual IRQ */
		virq = irq_create_mapping(NULL, irqs[i]);
		if (!virq) {
			pr_warn("Failed to map irq 0x%x\n", irqs[i]);
			continue;
		}

		if (names[i] && strlen(names[i]))
			name = kasprintf(GFP_KERNEL, "opal-%s", names[i]);
		else
			name = kasprintf(GFP_KERNEL, "opal");

		/* Install interrupt handler */
		rc = request_irq(virq, opal_interrupt, IRQF_TRIGGER_LOW,
				 name, NULL);
		if (rc) {
			irq_dispose_mapping(virq);
			pr_warn("Error %d requesting irq %d (0x%x)\n",
				 rc, virq, irqs[i]);
			continue;
		}

		/* Cache IRQ */
		opal_irqs[i] = virq;
	}

out_free:
	kfree(irqs);
	kfree(names);
out:
	of_node_put(opal_node);
	return rc;
}
machine_arch_initcall(powernv, opal_event_init);

/**
 * opal_event_request(unsigned int opal_event_nr) - Request an event
 * @opal_event_nr: the opal event number to request
 *
 * This routine can be used to find the linux virq number which can
 * then be passed to request_irq to assign a handler for a particular
 * opal event. This should only be used by legacy devices which don't
 * have proper device tree bindings. Most devices should use
 * irq_of_parse_and_map() instead.
 */
int opal_event_request(unsigned int opal_event_nr)
{
	if (WARN_ON_ONCE(!opal_event_irqchip.domain))
		return 0;

	return irq_create_mapping(opal_event_irqchip.domain, opal_event_nr);
}
EXPORT_SYMBOL(opal_event_request);
