]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/alpine-hal/al_hal_iofic.c
Upgrade to version 3.1.6
[FreeBSD/FreeBSD.git] / sys / contrib / alpine-hal / al_hal_iofic.c
1 /*-
2 *******************************************************************************
3 Copyright (C) 2015 Annapurna Labs Ltd.
4
5 This file may be licensed under the terms of the Annapurna Labs Commercial
6 License Agreement.
7
8 Alternatively, this file can be distributed under the terms of the GNU General
9 Public License V2 as published by the Free Software Foundation and can be
10 found at http://www.gnu.org/licenses/gpl-2.0.html
11
12 Alternatively, redistribution and use in source and binary forms, with or
13 without modification, are permitted provided that the following conditions are
14 met:
15
16     *     Redistributions of source code must retain the above copyright notice,
17 this list of conditions and the following disclaimer.
18
19     *     Redistributions in binary form must reproduce the above copyright
20 notice, this list of conditions and the following disclaimer in
21 the documentation and/or other materials provided with the
22 distribution.
23
24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
28 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35 *******************************************************************************/
36
37 /**
38  *  @{
39  * @file   al_hal_iofic.c
40  *
41  * @brief  interrupt controller hal
42  *
43  */
44
45 #include "al_hal_iofic.h"
46 #include "al_hal_iofic_regs.h"
47
48 /*
49  * configure the interrupt registers, interrupts will are kept masked
50  */
51 int al_iofic_config(void __iomem *regs_base, int group, uint32_t flags)
52 {
53         struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
54
55         al_assert(regs_base);
56         al_assert(group < AL_IOFIC_MAX_GROUPS);
57
58         al_reg_write32(&regs->ctrl[group].int_control_grp, flags);
59
60         return 0;
61 }
62
63 /*
64  * configure the moderation timer resolution for a given group
65  */
66 int al_iofic_moder_res_config(void __iomem *regs_base, int group,
67                              uint8_t resolution)
68
69 {
70         struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
71         uint32_t reg;
72
73         al_assert(regs_base);
74         al_assert(group < AL_IOFIC_MAX_GROUPS);
75
76         reg = al_reg_read32(&regs->ctrl[group].int_control_grp);
77         AL_REG_FIELD_SET(reg,
78                          INT_CONTROL_GRP_MOD_RES_MASK,
79                          INT_CONTROL_GRP_MOD_RES_SHIFT,
80                          resolution);
81         al_reg_write32(&regs->ctrl[group].int_control_grp, reg);
82
83         return 0;
84 }
85
86 /*
87  * configure the moderation timer interval for a given legacy interrupt group
88  */
89 int al_iofic_legacy_moder_interval_config(void __iomem *regs_base, int group,
90                                      uint8_t interval)
91 {
92         struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
93         uint32_t reg;
94
95         al_assert(regs_base);
96         al_assert(group < AL_IOFIC_MAX_GROUPS);
97
98         reg = al_reg_read32(&regs->ctrl[group].int_control_grp);
99         AL_REG_FIELD_SET(reg,
100                          INT_CONTROL_GRP_MOD_INTV_MASK,
101                          INT_CONTROL_GRP_MOD_INTV_SHIFT,
102                          interval);
103         al_reg_write32(&regs->ctrl[group].int_control_grp, reg);
104
105         return 0;
106 }
107
108
109 /*
110  * configure the moderation timer interval for a given msix vector.
111  */
112 int al_iofic_msix_moder_interval_config(void __iomem *regs_base, int group,
113                                        uint8_t vector, uint8_t interval)
114 {
115         struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
116         uint32_t reg;
117
118         al_assert(regs_base);
119         al_assert(group < AL_IOFIC_MAX_GROUPS);
120
121         reg = al_reg_read32(&regs->grp_int_mod[group][vector].grp_int_mod_reg);
122         AL_REG_FIELD_SET(reg,
123                          INT_MOD_INTV_MASK,
124                          INT_MOD_INTV_SHIFT,
125                          interval);
126         al_reg_write32(&regs->grp_int_mod[group][vector].grp_int_mod_reg, reg);
127
128         return 0;
129 }
130
131 /*
132  * configure the target-id attributes for a given msix vector.
133  */
134 int al_iofic_msix_tgtid_attributes_config(void __iomem *regs_base, int group,
135                                        uint8_t vector, uint32_t tgtid, uint8_t tgtid_en)
136 {
137         struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
138         uint32_t reg = 0;
139
140         al_assert(regs_base);
141         al_assert(group < AL_IOFIC_MAX_GROUPS);
142
143         AL_REG_FIELD_SET(reg,
144                          INT_MSIX_TGTID_MASK,
145                          INT_MSIX_TGTID_SHIFT,
146                          tgtid);
147         AL_REG_BIT_VAL_SET(reg,
148                          INT_MSIX_TGTID_EN_SHIFT,
149                          tgtid_en);
150
151         al_reg_write32(&regs->grp_int_mod[group][vector].grp_int_tgtid_reg, reg);
152
153         return 0;
154 }
155
156 /*
157  * return the offset of the unmask register for a given group
158  */
159 uint32_t __iomem * al_iofic_unmask_offset_get(void __iomem *regs_base, int group)
160 {
161         struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
162
163         al_assert(regs_base);
164         al_assert(group < AL_IOFIC_MAX_GROUPS);
165
166         return &regs->ctrl[group].int_mask_clear_grp;
167 }
168
169
170 /*
171  * unmask specific interrupts for a given group
172  */
173 void al_iofic_unmask(void __iomem *regs_base, int group, uint32_t mask)
174 {
175         struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
176
177         al_assert(regs_base);
178         al_assert(group < AL_IOFIC_MAX_GROUPS);
179
180         /*
181          * use the mask clear register, no need to read the mask register
182          * itself. write 0 to unmask, 1 has no effect
183          */
184         al_reg_write32_relaxed(&regs->ctrl[group].int_mask_clear_grp, ~mask);
185 }
186
187 /*
188  * mask specific interrupts for a given group
189  */
190 void al_iofic_mask(void __iomem *regs_base, int group, uint32_t mask)
191 {
192         struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
193         uint32_t reg;
194
195         al_assert(regs_base);
196         al_assert(group < AL_IOFIC_MAX_GROUPS);
197
198         reg = al_reg_read32(&regs->ctrl[group].int_mask_grp);
199
200         al_reg_write32(&regs->ctrl[group].int_mask_grp, reg | mask);
201 }
202
203 /*
204  * read the mask for a given group
205  */
206 uint32_t al_iofic_read_mask(void __iomem *regs_base, int group)
207 {
208         struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
209
210         al_assert(regs_base);
211         al_assert(group < AL_IOFIC_MAX_GROUPS);
212
213         return al_reg_read32(&regs->ctrl[group].int_mask_grp);
214 }
215
216 /*
217  * read interrupt cause register for a given group
218  */
219 uint32_t al_iofic_read_cause(void __iomem *regs_base, int group)
220 {
221         struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
222
223         al_assert(regs_base);
224         al_assert(group < AL_IOFIC_MAX_GROUPS);
225
226         return al_reg_read32(&regs->ctrl[group].int_cause_grp);
227 }
228
229 /*
230  * clear bits in the interrupt cause register for a given group
231  */
232 void al_iofic_clear_cause(void __iomem *regs_base, int group, uint32_t mask)
233 {
234         struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
235
236         al_assert(regs_base);
237         al_assert(group < AL_IOFIC_MAX_GROUPS);
238
239         /* inverse mask, writing 1 has no effect */
240         al_reg_write32(&regs->ctrl[group].int_cause_grp, ~mask);
241 }
242
243 /*
244  * Set the cause register for a given group
245  */
246 void al_iofic_set_cause(void __iomem *regs_base, int group, uint32_t mask)
247 {
248         struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
249
250         al_assert(regs_base);
251         al_assert(group < AL_IOFIC_MAX_GROUPS);
252
253         al_reg_write32(&regs->ctrl[group].int_cause_set_grp, mask);
254 }
255
256
257 /*
258  * unmask specific interrupts from aborting the udma a given group
259  */
260 void al_iofic_abort_mask(void __iomem *regs_base, int group, uint32_t mask)
261 {
262         struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
263
264         al_assert(regs_base);
265         al_assert(group < AL_IOFIC_MAX_GROUPS);
266
267         al_reg_write32(&regs->ctrl[group].int_abort_msk_grp, mask);
268
269 }
270
271 /*
272  * trigger all interrupts that are waiting for moderation timers to expire
273  */
274 void al_iofic_interrupt_moderation_reset(void __iomem *regs_base, int group)
275 {
276         struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
277         uint32_t reg = 0;
278
279         al_assert(regs_base);
280         al_assert(group < AL_IOFIC_MAX_GROUPS);
281
282         al_assert(regs_base);
283         al_assert(group < AL_IOFIC_MAX_GROUPS);
284
285         reg = al_reg_read32(&regs->ctrl[group].int_control_grp);
286         reg |= INT_CONTROL_GRP_MOD_RST;
287
288         al_reg_write32(&regs->ctrl[group].int_control_grp, reg);
289 }
290
291 /** @} end of interrupt controller group */