/*
 * Copyright 2023 NXP
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include "sw_isr_common.h"

#include <zephyr/sw_isr_table.h>
#include <zephyr/spinlock.h>

/* an interrupt line can be considered shared only if there's
 * at least 2 clients using it. As such, enforce the fact that
 * the maximum number of allowed clients should be at least 2.
 */
BUILD_ASSERT(CONFIG_SHARED_IRQ_MAX_NUM_CLIENTS >= 2,
	     "maximum number of clients should be at least 2");

void z_shared_isr(const void *data)
{
	size_t i;
	const struct z_shared_isr_table_entry *entry;
	const struct _isr_table_entry *client;

	entry = data;

	for (i = 0; i < entry->client_num; i++) {
		client = &entry->clients[i];

		if (client->isr) {
			client->isr(client->arg);
		}
	}
}

#ifdef CONFIG_DYNAMIC_INTERRUPTS

static struct k_spinlock lock;

void z_isr_install(unsigned int irq, void (*routine)(const void *),
		   const void *param)
{
	struct z_shared_isr_table_entry *shared_entry;
	struct _isr_table_entry *entry;
	struct _isr_table_entry *client;
	unsigned int table_idx;
	int i;
	k_spinlock_key_t key;

	table_idx = z_get_sw_isr_table_idx(irq);

	/* check for out of bounds table index */
	if (table_idx >= IRQ_TABLE_SIZE) {
		return;
	}

	shared_entry = &z_shared_sw_isr_table[table_idx];
	entry = &_sw_isr_table[table_idx];

	key = k_spin_lock(&lock);

	/* have we reached the client limit? */
	__ASSERT(shared_entry->client_num < CONFIG_SHARED_IRQ_MAX_NUM_CLIENTS,
		 "reached maximum number of clients");

	if (entry->isr == z_irq_spurious) {
		/* this is the first time a ISR/arg pair is registered
		 * for INTID => no need to share it.
		 */
		entry->isr = routine;
		entry->arg = param;

		k_spin_unlock(&lock, key);

		return;
	} else if (entry->isr != z_shared_isr) {
		/* INTID is being used by another ISR/arg pair.
		 * Push back the ISR/arg pair registered in _sw_isr_table
		 * to the list of clients and hijack the pair stored in
		 * _sw_isr_table with our own z_shared_isr/shared_entry pair.
		 */
		shared_entry->clients[shared_entry->client_num].isr = entry->isr;
		shared_entry->clients[shared_entry->client_num].arg = entry->arg;

		shared_entry->client_num++;

		entry->isr = z_shared_isr;
		entry->arg = shared_entry;
	}

	/* don't register the same ISR/arg pair multiple times */
	for (i = 0; i < shared_entry->client_num; i++) {
		client = &shared_entry->clients[i];

		__ASSERT((client->isr == routine && client->arg == param) == false,
			 "ISR/arg combination is already registered");
	}

	shared_entry->clients[shared_entry->client_num].isr = routine;
	shared_entry->clients[shared_entry->client_num].arg = param;
	shared_entry->client_num++;

	k_spin_unlock(&lock, key);
}

static void swap_client_data(struct _isr_table_entry *a,
			     struct _isr_table_entry *b)
{
	struct _isr_table_entry tmp;

	tmp.arg = a->arg;
	tmp.isr = a->isr;

	a->arg = b->arg;
	a->isr = b->isr;

	b->arg = tmp.arg;
	b->isr = tmp.isr;
}

static void shared_irq_remove_client(struct z_shared_isr_table_entry *shared_entry,
				     int client_idx, unsigned int table_idx)
{
	int i;

	shared_entry->clients[client_idx].isr = NULL;
	shared_entry->clients[client_idx].arg = NULL;

	/* push back the removed client to the end of the client list */
	for (i = client_idx; i <= (int)shared_entry->client_num - 2; i++) {
		swap_client_data(&shared_entry->clients[i],
				 &shared_entry->clients[i + 1]);
	}

	shared_entry->client_num--;

	/* "unshare" interrupt if there will be a single client left */
	if (shared_entry->client_num == 1) {
		_sw_isr_table[table_idx].isr = shared_entry->clients[0].isr;
		_sw_isr_table[table_idx].arg = shared_entry->clients[0].arg;

		shared_entry->clients[0].isr = NULL;
		shared_entry->clients[0].arg = NULL;

		shared_entry->client_num--;
	}
}

int __weak arch_irq_disconnect_dynamic(unsigned int irq, unsigned int priority,
				       void (*routine)(const void *parameter),
				       const void *parameter, uint32_t flags)
{
	ARG_UNUSED(priority);
	ARG_UNUSED(flags);

	return z_isr_uninstall(irq, routine, parameter);
}

int z_isr_uninstall(unsigned int irq,
		    void (*routine)(const void *),
		    const void *parameter)
{
	struct z_shared_isr_table_entry *shared_entry;
	struct _isr_table_entry *entry;
	struct _isr_table_entry *client;
	unsigned int table_idx;
	size_t i;
	k_spinlock_key_t key;

	table_idx = z_get_sw_isr_table_idx(irq);

	/* check for out of bounds table index */
	if (table_idx >= IRQ_TABLE_SIZE) {
		return -EINVAL;
	}

	shared_entry = &z_shared_sw_isr_table[table_idx];
	entry = &_sw_isr_table[table_idx];

	key = k_spin_lock(&lock);

	/* note: it's important that we remove the ISR/arg pair even if
	 * the IRQ line is not being shared because z_isr_install() will
	 * not overwrite it unless the _sw_isr_table entry for the given
	 * IRQ line contains the default pair which is z_irq_spurious/NULL.
	 */
	if (!shared_entry->client_num) {
		if (entry->isr == routine && entry->arg == parameter) {
			entry->isr = z_irq_spurious;
			entry->arg = NULL;
		}

		goto out_unlock;
	}

	for (i = 0; i < shared_entry->client_num; i++) {
		client = &shared_entry->clients[i];

		if (client->isr == routine && client->arg == parameter) {
			/* note: this is the only match we're going to get */
			shared_irq_remove_client(shared_entry, i, table_idx);
			goto out_unlock;
		}
	}

out_unlock:
	k_spin_unlock(&lock, key);
	return 0;
}

#endif /* CONFIG_DYNAMIC_INTERRUPTS */
