// SPDX-License-Identifier: GPL-2.0

/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
 * Copyright (C) 2018-2022 Linaro Ltd.
 */

/* DOC: IPA Interrupts
 *
 * The IPA has an interrupt line distinct from the interrupt used by the GSI
 * code.  Whereas GSI interrupts are generally related to channel events (like
 * transfer completions), IPA interrupts are related to other events related
 * to the IPA.  Some of the IPA interrupts come from a microcontroller
 * embedded in the IPA.  Each IPA interrupt type can be both masked and
 * acknowledged independent of the others.
 *
 * Two of the IPA interrupts are initiated by the microcontroller.  A third
 * can be generated to signal the need for a wakeup/resume when an IPA
 * endpoint has been suspended.  There are other IPA events, but at this
 * time only these three are supported.
 */

#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
#include <linux/pm_wakeirq.h>

#include "ipa.h"
#include "ipa_reg.h"
#include "ipa_endpoint.h"
#include "ipa_power.h"
#include "ipa_uc.h"
#include "ipa_interrupt.h"

/**
 * struct ipa_interrupt - IPA interrupt information
 * @ipa:		IPA pointer
 * @irq:		Linux IRQ number used for IPA interrupts
 * @enabled:		Mask indicating which interrupts are enabled
 */
struct ipa_interrupt {
	struct ipa *ipa;
	u32 irq;
	u32 enabled;
};

/* Process a particular interrupt type that has been received */
static void ipa_interrupt_process(struct ipa_interrupt *interrupt, u32 irq_id)
{
	struct ipa *ipa = interrupt->ipa;
	const struct reg *reg;
	u32 mask = BIT(irq_id);
	u32 offset;

	reg = ipa_reg(ipa, IPA_IRQ_CLR);
	offset = reg_offset(reg);

	switch (irq_id) {
	case IPA_IRQ_UC_0:
	case IPA_IRQ_UC_1:
		/* For microcontroller interrupts, clear the interrupt right
		 * away, "to avoid clearing unhandled interrupts."
		 */
		iowrite32(mask, ipa->reg_virt + offset);
		ipa_uc_interrupt_handler(ipa, irq_id);
		break;

	case IPA_IRQ_TX_SUSPEND:
		/* Clearing the SUSPEND_TX interrupt also clears the
		 * register that tells us which suspended endpoint(s)
		 * caused the interrupt, so defer clearing until after
		 * the handler has been called.
		 */
		ipa_power_suspend_handler(ipa, irq_id);
		fallthrough;

	default:	/* Silently ignore (and clear) any other condition */
		iowrite32(mask, ipa->reg_virt + offset);
		break;
	}
}

/* IPA IRQ handler is threaded */
static irqreturn_t ipa_isr_thread(int irq, void *dev_id)
{
	struct ipa_interrupt *interrupt = dev_id;
	struct ipa *ipa = interrupt->ipa;
	u32 enabled = interrupt->enabled;
	const struct reg *reg;
	struct device *dev;
	u32 pending;
	u32 offset;
	u32 mask;
	int ret;

	dev = &ipa->pdev->dev;
	ret = pm_runtime_get_sync(dev);
	if (WARN_ON(ret < 0))
		goto out_power_put;

	/* The status register indicates which conditions are present,
	 * including conditions whose interrupt is not enabled.  Handle
	 * only the enabled ones.
	 */
	reg = ipa_reg(ipa, IPA_IRQ_STTS);
	offset = reg_offset(reg);
	pending = ioread32(ipa->reg_virt + offset);
	while ((mask = pending & enabled)) {
		do {
			u32 irq_id = __ffs(mask);

			mask ^= BIT(irq_id);

			ipa_interrupt_process(interrupt, irq_id);
		} while (mask);
		pending = ioread32(ipa->reg_virt + offset);
	}

	/* If any disabled interrupts are pending, clear them */
	if (pending) {
		dev_dbg(dev, "clearing disabled IPA interrupts 0x%08x\n",
			pending);
		reg = ipa_reg(ipa, IPA_IRQ_CLR);
		iowrite32(pending, ipa->reg_virt + reg_offset(reg));
	}
out_power_put:
	pm_runtime_mark_last_busy(dev);
	(void)pm_runtime_put_autosuspend(dev);

	return IRQ_HANDLED;
}

static void ipa_interrupt_enabled_update(struct ipa *ipa)
{
	const struct reg *reg = ipa_reg(ipa, IPA_IRQ_EN);

	iowrite32(ipa->interrupt->enabled, ipa->reg_virt + reg_offset(reg));
}

/* Enable an IPA interrupt type */
void ipa_interrupt_enable(struct ipa *ipa, enum ipa_irq_id ipa_irq)
{
	/* Update the IPA interrupt mask to enable it */
	ipa->interrupt->enabled |= BIT(ipa_irq);
	ipa_interrupt_enabled_update(ipa);
}

/* Disable an IPA interrupt type */
void ipa_interrupt_disable(struct ipa *ipa, enum ipa_irq_id ipa_irq)
{
	/* Update the IPA interrupt mask to disable it */
	ipa->interrupt->enabled &= ~BIT(ipa_irq);
	ipa_interrupt_enabled_update(ipa);
}

void ipa_interrupt_irq_disable(struct ipa *ipa)
{
	disable_irq(ipa->interrupt->irq);
}

void ipa_interrupt_irq_enable(struct ipa *ipa)
{
	enable_irq(ipa->interrupt->irq);
}

/* Common function used to enable/disable TX_SUSPEND for an endpoint */
static void ipa_interrupt_suspend_control(struct ipa_interrupt *interrupt,
					  u32 endpoint_id, bool enable)
{
	struct ipa *ipa = interrupt->ipa;
	u32 mask = BIT(endpoint_id % 32);
	u32 unit = endpoint_id / 32;
	const struct reg *reg;
	u32 offset;
	u32 val;

	WARN_ON(!test_bit(endpoint_id, ipa->available));

	/* IPA version 3.0 does not support TX_SUSPEND interrupt control */
	if (ipa->version == IPA_VERSION_3_0)
		return;

	reg = ipa_reg(ipa, IRQ_SUSPEND_EN);
	offset = reg_n_offset(reg, unit);
	val = ioread32(ipa->reg_virt + offset);

	if (enable)
		val |= mask;
	else
		val &= ~mask;

	iowrite32(val, ipa->reg_virt + offset);
}

/* Enable TX_SUSPEND for an endpoint */
void
ipa_interrupt_suspend_enable(struct ipa_interrupt *interrupt, u32 endpoint_id)
{
	ipa_interrupt_suspend_control(interrupt, endpoint_id, true);
}

/* Disable TX_SUSPEND for an endpoint */
void
ipa_interrupt_suspend_disable(struct ipa_interrupt *interrupt, u32 endpoint_id)
{
	ipa_interrupt_suspend_control(interrupt, endpoint_id, false);
}

/* Clear the suspend interrupt for all endpoints that signaled it */
void ipa_interrupt_suspend_clear_all(struct ipa_interrupt *interrupt)
{
	struct ipa *ipa = interrupt->ipa;
	u32 unit_count;
	u32 unit;

	unit_count = roundup(ipa->endpoint_count, 32);
	for (unit = 0; unit < unit_count; unit++) {
		const struct reg *reg;
		u32 val;

		reg = ipa_reg(ipa, IRQ_SUSPEND_INFO);
		val = ioread32(ipa->reg_virt + reg_n_offset(reg, unit));

		/* SUSPEND interrupt status isn't cleared on IPA version 3.0 */
		if (ipa->version == IPA_VERSION_3_0)
			continue;

		reg = ipa_reg(ipa, IRQ_SUSPEND_CLR);
		iowrite32(val, ipa->reg_virt + reg_n_offset(reg, unit));
	}
}

/* Simulate arrival of an IPA TX_SUSPEND interrupt */
void ipa_interrupt_simulate_suspend(struct ipa_interrupt *interrupt)
{
	ipa_interrupt_process(interrupt, IPA_IRQ_TX_SUSPEND);
}

/* Configure the IPA interrupt framework */
struct ipa_interrupt *ipa_interrupt_config(struct ipa *ipa)
{
	struct device *dev = &ipa->pdev->dev;
	struct ipa_interrupt *interrupt;
	const struct reg *reg;
	unsigned int irq;
	int ret;

	ret = platform_get_irq_byname(ipa->pdev, "ipa");
	if (ret <= 0) {
		dev_err(dev, "DT error %d getting \"ipa\" IRQ property\n",
			ret);
		return ERR_PTR(ret ? : -EINVAL);
	}
	irq = ret;

	interrupt = kzalloc(sizeof(*interrupt), GFP_KERNEL);
	if (!interrupt)
		return ERR_PTR(-ENOMEM);
	interrupt->ipa = ipa;
	interrupt->irq = irq;

	/* Start with all IPA interrupts disabled */
	reg = ipa_reg(ipa, IPA_IRQ_EN);
	iowrite32(0, ipa->reg_virt + reg_offset(reg));

	ret = request_threaded_irq(irq, NULL, ipa_isr_thread, IRQF_ONESHOT,
				   "ipa", interrupt);
	if (ret) {
		dev_err(dev, "error %d requesting \"ipa\" IRQ\n", ret);
		goto err_kfree;
	}

	ret = dev_pm_set_wake_irq(dev, irq);
	if (ret) {
		dev_err(dev, "error %d registering \"ipa\" IRQ as wakeirq\n", ret);
		goto err_free_irq;
	}

	return interrupt;

err_free_irq:
	free_irq(interrupt->irq, interrupt);
err_kfree:
	kfree(interrupt);

	return ERR_PTR(ret);
}

/* Inverse of ipa_interrupt_config() */
void ipa_interrupt_deconfig(struct ipa_interrupt *interrupt)
{
	struct device *dev = &interrupt->ipa->pdev->dev;

	dev_pm_clear_wake_irq(dev);
	free_irq(interrupt->irq, interrupt);
	kfree(interrupt);
}
