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 */
65struct 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__
78static_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
85struct 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 */
94enum 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 */
107enum 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
116static inline void
117pds_core_intr_coal_init(struct pds_core_intr __iomem *intr_ctrl, u32 coal)
118{
119 iowrite32(coal, &intr_ctrl->coal_init);
120}
121
122static inline void
123pds_core_intr_mask(struct pds_core_intr __iomem *intr_ctrl, u32 mask)
124{
125 iowrite32(mask, &intr_ctrl->mask);
126}
127
128static inline void
129pds_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
140static inline void
141pds_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
151static inline void
152pds_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
157static inline void
158pds_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

source code of linux/include/linux/pds/pds_intr.h