1 | /* SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB) OR BSD-2-Clause */ |
2 | /* Copyright(c) 2023 Advanced Micro Devices, Inc. */ |
3 | |
4 | #ifndef _PDS_INTR_H_ |
5 | #define _PDS_INTR_H_ |
6 | |
7 | /* |
8 | * Interrupt control register |
9 | * @coal_init: Coalescing timer initial value, in |
10 | * device units. Use @identity->intr_coal_mult |
11 | * and @identity->intr_coal_div to convert from |
12 | * usecs to device units: |
13 | * |
14 | * coal_init = coal_usecs * coal_mutl / coal_div |
15 | * |
16 | * When an interrupt is sent the interrupt |
17 | * coalescing timer current value |
18 | * (@coalescing_curr) is initialized with this |
19 | * value and begins counting down. No more |
20 | * interrupts are sent until the coalescing |
21 | * timer reaches 0. When @coalescing_init=0 |
22 | * interrupt coalescing is effectively disabled |
23 | * and every interrupt assert results in an |
24 | * interrupt. Reset value: 0 |
25 | * @mask: Interrupt mask. When @mask=1 the interrupt |
26 | * resource will not send an interrupt. When |
27 | * @mask=0 the interrupt resource will send an |
28 | * interrupt if an interrupt event is pending |
29 | * or on the next interrupt assertion event. |
30 | * Reset value: 1 |
31 | * @credits: Interrupt credits. This register indicates |
32 | * how many interrupt events the hardware has |
33 | * sent. When written by software this |
34 | * register atomically decrements @int_credits |
35 | * by the value written. When @int_credits |
36 | * becomes 0 then the "pending interrupt" bit |
37 | * in the Interrupt Status register is cleared |
38 | * by the hardware and any pending but unsent |
39 | * interrupts are cleared. |
40 | * !!!IMPORTANT!!! This is a signed register. |
41 | * @flags: Interrupt control flags |
42 | * @unmask -- When this bit is written with a 1 |
43 | * the interrupt resource will set mask=0. |
44 | * @coal_timer_reset -- When this |
45 | * bit is written with a 1 the |
46 | * @coalescing_curr will be reloaded with |
47 | * @coalescing_init to reset the coalescing |
48 | * timer. |
49 | * @mask_on_assert: Automatically mask on assertion. When |
50 | * @mask_on_assert=1 the interrupt resource |
51 | * will set @mask=1 whenever an interrupt is |
52 | * sent. When using interrupts in Legacy |
53 | * Interrupt mode the driver must select |
54 | * @mask_on_assert=0 for proper interrupt |
55 | * operation. |
56 | * @coalescing_curr: Coalescing timer current value, in |
57 | * microseconds. When this value reaches 0 |
58 | * the interrupt resource is again eligible to |
59 | * send an interrupt. If an interrupt event |
60 | * is already pending when @coalescing_curr |
61 | * reaches 0 the pending interrupt will be |
62 | * sent, otherwise an interrupt will be sent |
63 | * on the next interrupt assertion event. |
64 | */ |
65 | struct pds_core_intr { |
66 | u32 coal_init; |
67 | u32 mask; |
68 | u16 credits; |
69 | u16 flags; |
70 | #define PDS_CORE_INTR_F_UNMASK 0x0001 |
71 | #define PDS_CORE_INTR_F_TIMER_RESET 0x0002 |
72 | u32 mask_on_assert; |
73 | u32 coalescing_curr; |
74 | u32 rsvd6[3]; |
75 | }; |
76 | |
77 | #ifndef __CHECKER__ |
78 | static_assert(sizeof(struct pds_core_intr) == 32); |
79 | #endif /* __CHECKER__ */ |
80 | |
81 | #define PDS_CORE_INTR_CTRL_REGS_MAX 2048 |
82 | #define PDS_CORE_INTR_CTRL_COAL_MAX 0x3F |
83 | #define PDS_CORE_INTR_INDEX_NOT_ASSIGNED -1 |
84 | |
85 | struct pds_core_intr_status { |
86 | u32 status[2]; |
87 | }; |
88 | |
89 | /** |
90 | * enum pds_core_intr_mask_vals - valid values for mask and mask_assert. |
91 | * @PDS_CORE_INTR_MASK_CLEAR: unmask interrupt. |
92 | * @PDS_CORE_INTR_MASK_SET: mask interrupt. |
93 | */ |
94 | enum pds_core_intr_mask_vals { |
95 | PDS_CORE_INTR_MASK_CLEAR = 0, |
96 | PDS_CORE_INTR_MASK_SET = 1, |
97 | }; |
98 | |
99 | /** |
100 | * enum pds_core_intr_credits_bits - Bitwise composition of credits values. |
101 | * @PDS_CORE_INTR_CRED_COUNT: bit mask of credit count, no shift needed. |
102 | * @PDS_CORE_INTR_CRED_COUNT_SIGNED: bit mask of credit count, including sign bit. |
103 | * @PDS_CORE_INTR_CRED_UNMASK: unmask the interrupt. |
104 | * @PDS_CORE_INTR_CRED_RESET_COALESCE: reset the coalesce timer. |
105 | * @PDS_CORE_INTR_CRED_REARM: unmask the and reset the timer. |
106 | */ |
107 | enum pds_core_intr_credits_bits { |
108 | PDS_CORE_INTR_CRED_COUNT = 0x7fffu, |
109 | PDS_CORE_INTR_CRED_COUNT_SIGNED = 0xffffu, |
110 | PDS_CORE_INTR_CRED_UNMASK = 0x10000u, |
111 | PDS_CORE_INTR_CRED_RESET_COALESCE = 0x20000u, |
112 | PDS_CORE_INTR_CRED_REARM = (PDS_CORE_INTR_CRED_UNMASK | |
113 | PDS_CORE_INTR_CRED_RESET_COALESCE), |
114 | }; |
115 | |
116 | static inline void |
117 | pds_core_intr_coal_init(struct pds_core_intr __iomem *intr_ctrl, u32 coal) |
118 | { |
119 | iowrite32(coal, &intr_ctrl->coal_init); |
120 | } |
121 | |
122 | static inline void |
123 | pds_core_intr_mask(struct pds_core_intr __iomem *intr_ctrl, u32 mask) |
124 | { |
125 | iowrite32(mask, &intr_ctrl->mask); |
126 | } |
127 | |
128 | static inline void |
129 | pds_core_intr_credits(struct pds_core_intr __iomem *intr_ctrl, |
130 | u32 cred, u32 flags) |
131 | { |
132 | if (WARN_ON_ONCE(cred > PDS_CORE_INTR_CRED_COUNT)) { |
133 | cred = ioread32(&intr_ctrl->credits); |
134 | cred &= PDS_CORE_INTR_CRED_COUNT_SIGNED; |
135 | } |
136 | |
137 | iowrite32(cred | flags, &intr_ctrl->credits); |
138 | } |
139 | |
140 | static inline void |
141 | pds_core_intr_clean_flags(struct pds_core_intr __iomem *intr_ctrl, u32 flags) |
142 | { |
143 | u32 cred; |
144 | |
145 | cred = ioread32(&intr_ctrl->credits); |
146 | cred &= PDS_CORE_INTR_CRED_COUNT_SIGNED; |
147 | cred |= flags; |
148 | iowrite32(cred, &intr_ctrl->credits); |
149 | } |
150 | |
151 | static inline void |
152 | pds_core_intr_clean(struct pds_core_intr __iomem *intr_ctrl) |
153 | { |
154 | pds_core_intr_clean_flags(intr_ctrl, flags: PDS_CORE_INTR_CRED_RESET_COALESCE); |
155 | } |
156 | |
157 | static inline void |
158 | pds_core_intr_mask_assert(struct pds_core_intr __iomem *intr_ctrl, u32 mask) |
159 | { |
160 | iowrite32(mask, &intr_ctrl->mask_on_assert); |
161 | } |
162 | |
163 | #endif /* _PDS_INTR_H_ */ |
164 | |