1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright (C) 2021 Western Digital Corporation or its affiliates.
4 * Copyright (C) 2022 Ventana Micro Systems Inc.
5 */
6
7#ifndef _IRQ_RISCV_IMSIC_STATE_H
8#define _IRQ_RISCV_IMSIC_STATE_H
9
10#include <linux/irqchip/riscv-imsic.h>
11#include <linux/irqdomain.h>
12#include <linux/fwnode.h>
13#include <linux/timer.h>
14
15#define IMSIC_IPI_ID				1
16#define IMSIC_NR_IPI				8
17
18struct imsic_vector {
19	/* Fixed details of the vector */
20	unsigned int				cpu;
21	unsigned int				local_id;
22	/* Details saved by driver in the vector */
23	unsigned int				hwirq;
24	/* Details accessed using local lock held */
25	bool					enable;
26	struct imsic_vector			*move;
27};
28
29struct imsic_local_priv {
30	/* Local lock to protect vector enable/move variables and dirty bitmap */
31	raw_spinlock_t				lock;
32
33	/* Local dirty bitmap for synchronization */
34	unsigned long				*dirty_bitmap;
35
36#ifdef CONFIG_SMP
37	/* Local timer for synchronization */
38	struct timer_list			timer;
39#endif
40
41	/* Local vector table */
42	struct imsic_vector			*vectors;
43};
44
45struct imsic_priv {
46	/* Device details */
47	struct fwnode_handle			*fwnode;
48
49	/* Global configuration common for all HARTs */
50	struct imsic_global_config		global;
51
52	/* Per-CPU state */
53	struct imsic_local_priv __percpu	*lpriv;
54
55	/* State of IRQ matrix allocator */
56	raw_spinlock_t				matrix_lock;
57	struct irq_matrix			*matrix;
58
59	/* IRQ domains (created by platform driver) */
60	struct irq_domain			*base_domain;
61};
62
63extern struct imsic_priv *imsic;
64
65void __imsic_eix_update(unsigned long base_id, unsigned long num_id, bool pend, bool val);
66
67static inline void __imsic_id_set_enable(unsigned long id)
68{
69	__imsic_eix_update(id, 1, false, true);
70}
71
72static inline void __imsic_id_clear_enable(unsigned long id)
73{
74	__imsic_eix_update(id, 1, false, false);
75}
76
77void imsic_local_sync_all(void);
78void imsic_local_delivery(bool enable);
79
80void imsic_vector_mask(struct imsic_vector *vec);
81void imsic_vector_unmask(struct imsic_vector *vec);
82
83static inline bool imsic_vector_isenabled(struct imsic_vector *vec)
84{
85	return READ_ONCE(vec->enable);
86}
87
88static inline struct imsic_vector *imsic_vector_get_move(struct imsic_vector *vec)
89{
90	return READ_ONCE(vec->move);
91}
92
93void imsic_vector_move(struct imsic_vector *old_vec, struct imsic_vector *new_vec);
94
95struct imsic_vector *imsic_vector_from_local_id(unsigned int cpu, unsigned int local_id);
96
97struct imsic_vector *imsic_vector_alloc(unsigned int hwirq, const struct cpumask *mask);
98void imsic_vector_free(struct imsic_vector *vector);
99
100void imsic_vector_debug_show(struct seq_file *m, struct imsic_vector *vec, int ind);
101void imsic_vector_debug_show_summary(struct seq_file *m, int ind);
102
103void imsic_state_online(void);
104void imsic_state_offline(void);
105int imsic_setup_state(struct fwnode_handle *fwnode);
106int imsic_irqdomain_init(void);
107
108#endif
109