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 
18 struct 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 
29 struct 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 
45 struct 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 
63 extern struct imsic_priv *imsic;
64 
65 void __imsic_eix_update(unsigned long base_id, unsigned long num_id, bool pend, bool val);
66 
__imsic_id_set_enable(unsigned long id)67 static inline void __imsic_id_set_enable(unsigned long id)
68 {
69 	__imsic_eix_update(id, 1, false, true);
70 }
71 
__imsic_id_clear_enable(unsigned long id)72 static inline void __imsic_id_clear_enable(unsigned long id)
73 {
74 	__imsic_eix_update(id, 1, false, false);
75 }
76 
77 void imsic_local_sync_all(void);
78 void imsic_local_delivery(bool enable);
79 
80 void imsic_vector_mask(struct imsic_vector *vec);
81 void imsic_vector_unmask(struct imsic_vector *vec);
82 
imsic_vector_isenabled(struct imsic_vector * vec)83 static inline bool imsic_vector_isenabled(struct imsic_vector *vec)
84 {
85 	return READ_ONCE(vec->enable);
86 }
87 
imsic_vector_get_move(struct imsic_vector * vec)88 static inline struct imsic_vector *imsic_vector_get_move(struct imsic_vector *vec)
89 {
90 	return READ_ONCE(vec->move);
91 }
92 
93 void imsic_vector_move(struct imsic_vector *old_vec, struct imsic_vector *new_vec);
94 
95 struct imsic_vector *imsic_vector_from_local_id(unsigned int cpu, unsigned int local_id);
96 
97 struct imsic_vector *imsic_vector_alloc(unsigned int hwirq, const struct cpumask *mask);
98 void imsic_vector_free(struct imsic_vector *vector);
99 
100 void imsic_vector_debug_show(struct seq_file *m, struct imsic_vector *vec, int ind);
101 void imsic_vector_debug_show_summary(struct seq_file *m, int ind);
102 
103 void imsic_state_online(void);
104 void imsic_state_offline(void);
105 int imsic_setup_state(struct fwnode_handle *fwnode, void *opaque);
106 int imsic_irqdomain_init(void);
107 
108 #endif
109