/*
   forward-irq.h - driver for SoftLab-NSK Forward boards

   Copyright (C) 2017 - 2023 Konstantin Oblaukhov <oblaukhov@sl.iae.nsk.su>

   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.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#ifndef FORWARD_IRQ_H
#define FORWARD_IRQ_H

#include <linux/irq.h>

struct forward_dev;

#define FORWARD_IRQ_LISTENER_WAIT (1 << 0)
#define FORWARD_IRQ_LISTENER_CALLBACK (1 << 1)
#define FORWARD_IRQ_LISTENER_WORKQUEUE (1 << 2)

struct forward_irq_listener {
	struct list_head list;
	int type;
	u32 mask;
	u32 flags;
	u64 time;
	spinlock_t slock;
	wait_queue_head_t wait;
	struct work_struct work;
	int work_queue;
	int priority;
	void *private;
	void (*func)(void *, u32, u64);
	void (*wq_func)(void *, u32, u64);
};

void forward_irq_listener_init(struct forward_irq_listener *listener);
int forward_irq_listener_add(struct forward_dev *dev, struct forward_irq_listener *listener);
struct forward_irq_listener *forward_irq_listener_find(struct forward_dev *dev, void *private);
int forward_irq_listener_remove(struct forward_dev *dev, struct forward_irq_listener *listener);
u32 forward_irq_listener_wait(struct forward_irq_listener *listener, bool clear, int timeout);
u32 forward_irq_listener_wait_kthread(struct forward_irq_listener *listener, bool clear,
				      int timeout);
void forward_irq_listener_clear(struct forward_irq_listener *listener);

int forward_irq_probe(struct forward_dev *dev);
void forward_irq_remove(struct forward_dev *dev);

#endif
