1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright 2011-2012, Meador Inge, Mentor Graphics Corporation.
4  */
5 
6 #ifndef _ASM_MPIC_MSGR_H
7 #define _ASM_MPIC_MSGR_H
8 
9 #include <linux/types.h>
10 #include <linux/spinlock.h>
11 #include <asm/smp.h>
12 #include <asm/io.h>
13 
14 struct mpic_msgr {
15 	u32 __iomem *base;
16 	u32 __iomem *mer;
17 	int irq;
18 	unsigned char in_use;
19 	raw_spinlock_t lock;
20 	int num;
21 };
22 
23 /* Get a message register
24  *
25  * @reg_num:	the MPIC message register to get
26  *
27  * A pointer to the message register is returned.  If
28  * the message register asked for is already in use, then
29  * EBUSY is returned.  If the number given is not associated
30  * with an actual message register, then ENODEV is returned.
31  * Successfully getting the register marks it as in use.
32  */
33 extern struct mpic_msgr *mpic_msgr_get(unsigned int reg_num);
34 
35 /* Relinquish a message register
36  *
37  * @msgr:	the message register to return
38  *
39  * Disables the given message register and marks it as free.
40  * After this call has completed successully the message
41  * register is available to be acquired by a call to
42  * mpic_msgr_get.
43  */
44 extern void mpic_msgr_put(struct mpic_msgr *msgr);
45 
46 /* Enable a message register
47  *
48  * @msgr:	the message register to enable
49  *
50  * The given message register is enabled for sending
51  * messages.
52  */
53 extern void mpic_msgr_enable(struct mpic_msgr *msgr);
54 
55 /* Disable a message register
56  *
57  * @msgr:	the message register to disable
58  *
59  * The given message register is disabled for sending
60  * messages.
61  */
62 extern void mpic_msgr_disable(struct mpic_msgr *msgr);
63 
64 /* Write a message to a message register
65  *
66  * @msgr:	the message register to write to
67  * @message:	the message to write
68  *
69  * The given 32-bit message is written to the given message
70  * register.  Writing to an enabled message registers fires
71  * an interrupt.
72  */
73 static inline void mpic_msgr_write(struct mpic_msgr *msgr, u32 message)
74 {
75 	out_be32(msgr->base, message);
76 }
77 
78 /* Read a message from a message register
79  *
80  * @msgr:	the message register to read from
81  *
82  * Returns the 32-bit value currently in the given message register.
83  * Upon reading the register any interrupts for that register are
84  * cleared.
85  */
86 static inline u32 mpic_msgr_read(struct mpic_msgr *msgr)
87 {
88 	return in_be32(msgr->base);
89 }
90 
91 /* Clear a message register
92  *
93  * @msgr:	the message register to clear
94  *
95  * Clears any interrupts associated with the given message register.
96  */
97 static inline void mpic_msgr_clear(struct mpic_msgr *msgr)
98 {
99 	(void) mpic_msgr_read(msgr);
100 }
101 
102 /* Set the destination CPU for the message register
103  *
104  * @msgr:	the message register whose destination is to be set
105  * @cpu_num:	the Linux CPU number to bind the message register to
106  *
107  * Note that the CPU number given is the CPU number used by the kernel
108  * and *not* the actual hardware CPU number.
109  */
110 static inline void mpic_msgr_set_destination(struct mpic_msgr *msgr,
111 					     u32 cpu_num)
112 {
113 	out_be32(msgr->base, 1 << get_hard_smp_processor_id(cpu_num));
114 }
115 
116 /* Get the IRQ number for the message register
117  * @msgr:	the message register whose IRQ is to be returned
118  *
119  * Returns the IRQ number associated with the given message register.
120  * 0 is returned if this message register is not capable of receiving
121  * interrupts.  What message register can and cannot receive interrupts is
122  * specified in the device tree for the system.
123  */
124 static inline int mpic_msgr_get_irq(struct mpic_msgr *msgr)
125 {
126 	return msgr->irq;
127 }
128 
129 #endif
130