|  | /* SPDX-License-Identifier: GPL-2.0-only */ | 
|  | /* | 
|  | * Copyright (C) 2021 Western Digital Corporation or its affiliates. | 
|  | * Copyright (C) 2022 Ventana Micro Systems Inc. | 
|  | */ | 
|  |  | 
|  | #ifndef _IRQ_RISCV_IMSIC_STATE_H | 
|  | #define _IRQ_RISCV_IMSIC_STATE_H | 
|  |  | 
|  | #include <linux/irqchip/riscv-imsic.h> | 
|  | #include <linux/irqdomain.h> | 
|  | #include <linux/fwnode.h> | 
|  | #include <linux/timer.h> | 
|  |  | 
|  | #define IMSIC_IPI_ID				1 | 
|  | #define IMSIC_NR_IPI				8 | 
|  |  | 
|  | struct imsic_vector { | 
|  | /* Fixed details of the vector */ | 
|  | unsigned int				cpu; | 
|  | unsigned int				local_id; | 
|  | /* Details saved by driver in the vector */ | 
|  | unsigned int				hwirq; | 
|  | /* Details accessed using local lock held */ | 
|  | bool					enable; | 
|  | struct imsic_vector			*move; | 
|  | }; | 
|  |  | 
|  | struct imsic_local_priv { | 
|  | /* Local lock to protect vector enable/move variables and dirty bitmap */ | 
|  | raw_spinlock_t				lock; | 
|  |  | 
|  | /* Local dirty bitmap for synchronization */ | 
|  | unsigned long				*dirty_bitmap; | 
|  |  | 
|  | #ifdef CONFIG_SMP | 
|  | /* Local timer for synchronization */ | 
|  | struct timer_list			timer; | 
|  | #endif | 
|  |  | 
|  | /* Local vector table */ | 
|  | struct imsic_vector			*vectors; | 
|  | }; | 
|  |  | 
|  | struct imsic_priv { | 
|  | /* Device details */ | 
|  | struct fwnode_handle			*fwnode; | 
|  |  | 
|  | /* Global configuration common for all HARTs */ | 
|  | struct imsic_global_config		global; | 
|  |  | 
|  | /* Per-CPU state */ | 
|  | struct imsic_local_priv __percpu	*lpriv; | 
|  |  | 
|  | /* State of IRQ matrix allocator */ | 
|  | raw_spinlock_t				matrix_lock; | 
|  | struct irq_matrix			*matrix; | 
|  |  | 
|  | /* IRQ domains (created by platform driver) */ | 
|  | struct irq_domain			*base_domain; | 
|  | }; | 
|  |  | 
|  | extern struct imsic_priv *imsic; | 
|  |  | 
|  | void __imsic_eix_update(unsigned long base_id, unsigned long num_id, bool pend, bool val); | 
|  |  | 
|  | static inline void __imsic_id_set_enable(unsigned long id) | 
|  | { | 
|  | __imsic_eix_update(id, 1, false, true); | 
|  | } | 
|  |  | 
|  | static inline void __imsic_id_clear_enable(unsigned long id) | 
|  | { | 
|  | __imsic_eix_update(id, 1, false, false); | 
|  | } | 
|  |  | 
|  | void imsic_local_sync_all(void); | 
|  | void imsic_local_delivery(bool enable); | 
|  |  | 
|  | void imsic_vector_mask(struct imsic_vector *vec); | 
|  | void imsic_vector_unmask(struct imsic_vector *vec); | 
|  |  | 
|  | static inline bool imsic_vector_isenabled(struct imsic_vector *vec) | 
|  | { | 
|  | return READ_ONCE(vec->enable); | 
|  | } | 
|  |  | 
|  | static inline struct imsic_vector *imsic_vector_get_move(struct imsic_vector *vec) | 
|  | { | 
|  | return READ_ONCE(vec->move); | 
|  | } | 
|  |  | 
|  | void imsic_vector_move(struct imsic_vector *old_vec, struct imsic_vector *new_vec); | 
|  |  | 
|  | struct imsic_vector *imsic_vector_from_local_id(unsigned int cpu, unsigned int local_id); | 
|  |  | 
|  | struct imsic_vector *imsic_vector_alloc(unsigned int hwirq, const struct cpumask *mask); | 
|  | void imsic_vector_free(struct imsic_vector *vector); | 
|  |  | 
|  | void imsic_vector_debug_show(struct seq_file *m, struct imsic_vector *vec, int ind); | 
|  | void imsic_vector_debug_show_summary(struct seq_file *m, int ind); | 
|  |  | 
|  | void imsic_state_online(void); | 
|  | void imsic_state_offline(void); | 
|  | int imsic_setup_state(struct fwnode_handle *fwnode, void *opaque); | 
|  | int imsic_irqdomain_init(void); | 
|  |  | 
|  | #endif |