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				irq;
24 	/* Details accessed using local lock held */
25 	bool					enable;
26 	struct imsic_vector			*move_next;
27 	struct imsic_vector			*move_prev;
28 };
29 
30 struct imsic_local_priv {
31 	/* Local lock to protect vector enable/move variables and dirty bitmap */
32 	raw_spinlock_t				lock;
33 
34 	/* Local dirty bitmap for synchronization */
35 	unsigned long				*dirty_bitmap;
36 
37 #ifdef CONFIG_SMP
38 	/* Local timer for synchronization */
39 	struct timer_list			timer;
40 #endif
41 
42 	/* Local vector table */
43 	struct imsic_vector			*vectors;
44 };
45 
46 struct imsic_priv {
47 	/* Device details */
48 	struct fwnode_handle			*fwnode;
49 
50 	/* Global configuration common for all HARTs */
51 	struct imsic_global_config		global;
52 
53 	/* Per-CPU state */
54 	struct imsic_local_priv __percpu	*lpriv;
55 
56 	/* State of IRQ matrix allocator */
57 	raw_spinlock_t				matrix_lock;
58 	struct irq_matrix			*matrix;
59 
60 	/* IRQ domains (created by platform driver) */
61 	struct irq_domain			*base_domain;
62 };
63 
64 extern struct imsic_priv *imsic;
65 
66 void __imsic_eix_update(unsigned long base_id, unsigned long num_id, bool pend, bool val);
67 
__imsic_id_set_enable(unsigned long id)68 static inline void __imsic_id_set_enable(unsigned long id)
69 {
70 	__imsic_eix_update(id, 1, false, true);
71 }
72 
__imsic_id_clear_enable(unsigned long id)73 static inline void __imsic_id_clear_enable(unsigned long id)
74 {
75 	__imsic_eix_update(id, 1, false, false);
76 }
77 
78 void imsic_local_sync_all(bool force_all);
79 void imsic_local_delivery(bool enable);
80 
81 void imsic_vector_mask(struct imsic_vector *vec);
82 void imsic_vector_unmask(struct imsic_vector *vec);
83 
imsic_vector_isenabled(struct imsic_vector * vec)84 static inline bool imsic_vector_isenabled(struct imsic_vector *vec)
85 {
86 	return READ_ONCE(vec->enable);
87 }
88 
imsic_vector_get_move(struct imsic_vector * vec)89 static inline struct imsic_vector *imsic_vector_get_move(struct imsic_vector *vec)
90 {
91 	return READ_ONCE(vec->move_prev);
92 }
93 
94 void imsic_vector_force_move_cleanup(struct imsic_vector *vec);
95 void imsic_vector_move(struct imsic_vector *old_vec, struct imsic_vector *new_vec);
96 
97 struct imsic_vector *imsic_vector_from_local_id(unsigned int cpu, unsigned int local_id);
98 
99 struct imsic_vector *imsic_vector_alloc(unsigned int irq, const struct cpumask *mask);
100 void imsic_vector_free(struct imsic_vector *vector);
101 
102 void imsic_vector_debug_show(struct seq_file *m, struct imsic_vector *vec, int ind);
103 void imsic_vector_debug_show_summary(struct seq_file *m, int ind);
104 
105 void imsic_state_online(void);
106 void imsic_state_offline(void);
107 int imsic_setup_state(struct fwnode_handle *fwnode, void *opaque);
108 int imsic_irqdomain_init(void);
109 
110 #endif
111