2 *******************************************************************************
3 Copyright (C) 2015 Annapurna Labs Ltd.
5 This file may be licensed under the terms of the Annapurna Labs Commercial
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
12 Alternatively, redistribution and use in source and binary forms, with or
13 without modification, are permitted provided that the following conditions are
16 * Redistributions of source code must retain the above copyright notice,
17 this list of conditions and the following disclaimer.
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
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.
35 *******************************************************************************/
39 * @file al_hal_iofic.c
41 * @brief interrupt controller hal
45 #include "al_hal_iofic.h"
46 #include "al_hal_iofic_regs.h"
49 * configure the interrupt registers, interrupts will are kept masked
51 int al_iofic_config(void __iomem *regs_base, int group, uint32_t flags)
53 struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
56 al_assert(group < AL_IOFIC_MAX_GROUPS);
58 al_reg_write32(®s->ctrl[group].int_control_grp, flags);
64 * configure the moderation timer resolution for a given group
66 int al_iofic_moder_res_config(void __iomem *regs_base, int group,
70 struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
74 al_assert(group < AL_IOFIC_MAX_GROUPS);
76 reg = al_reg_read32(®s->ctrl[group].int_control_grp);
78 INT_CONTROL_GRP_MOD_RES_MASK,
79 INT_CONTROL_GRP_MOD_RES_SHIFT,
81 al_reg_write32(®s->ctrl[group].int_control_grp, reg);
87 * configure the moderation timer interval for a given legacy interrupt group
89 int al_iofic_legacy_moder_interval_config(void __iomem *regs_base, int group,
92 struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
96 al_assert(group < AL_IOFIC_MAX_GROUPS);
98 reg = al_reg_read32(®s->ctrl[group].int_control_grp);
100 INT_CONTROL_GRP_MOD_INTV_MASK,
101 INT_CONTROL_GRP_MOD_INTV_SHIFT,
103 al_reg_write32(®s->ctrl[group].int_control_grp, reg);
110 * configure the moderation timer interval for a given msix vector.
112 int al_iofic_msix_moder_interval_config(void __iomem *regs_base, int group,
113 uint8_t vector, uint8_t interval)
115 struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
118 al_assert(regs_base);
119 al_assert(group < AL_IOFIC_MAX_GROUPS);
121 reg = al_reg_read32(®s->grp_int_mod[group][vector].grp_int_mod_reg);
122 AL_REG_FIELD_SET(reg,
126 al_reg_write32(®s->grp_int_mod[group][vector].grp_int_mod_reg, reg);
132 * configure the target-id attributes for a given msix vector.
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)
137 struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
140 al_assert(regs_base);
141 al_assert(group < AL_IOFIC_MAX_GROUPS);
143 AL_REG_FIELD_SET(reg,
145 INT_MSIX_TGTID_SHIFT,
147 AL_REG_BIT_VAL_SET(reg,
148 INT_MSIX_TGTID_EN_SHIFT,
151 al_reg_write32(®s->grp_int_mod[group][vector].grp_int_tgtid_reg, reg);
157 * return the offset of the unmask register for a given group
159 uint32_t __iomem * al_iofic_unmask_offset_get(void __iomem *regs_base, int group)
161 struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
163 al_assert(regs_base);
164 al_assert(group < AL_IOFIC_MAX_GROUPS);
166 return ®s->ctrl[group].int_mask_clear_grp;
171 * unmask specific interrupts for a given group
173 void al_iofic_unmask(void __iomem *regs_base, int group, uint32_t mask)
175 struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
177 al_assert(regs_base);
178 al_assert(group < AL_IOFIC_MAX_GROUPS);
181 * use the mask clear register, no need to read the mask register
182 * itself. write 0 to unmask, 1 has no effect
184 al_reg_write32_relaxed(®s->ctrl[group].int_mask_clear_grp, ~mask);
188 * mask specific interrupts for a given group
190 void al_iofic_mask(void __iomem *regs_base, int group, uint32_t mask)
192 struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
195 al_assert(regs_base);
196 al_assert(group < AL_IOFIC_MAX_GROUPS);
198 reg = al_reg_read32(®s->ctrl[group].int_mask_grp);
200 al_reg_write32(®s->ctrl[group].int_mask_grp, reg | mask);
204 * read the mask for a given group
206 uint32_t al_iofic_read_mask(void __iomem *regs_base, int group)
208 struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
210 al_assert(regs_base);
211 al_assert(group < AL_IOFIC_MAX_GROUPS);
213 return al_reg_read32(®s->ctrl[group].int_mask_grp);
217 * read interrupt cause register for a given group
219 uint32_t al_iofic_read_cause(void __iomem *regs_base, int group)
221 struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
223 al_assert(regs_base);
224 al_assert(group < AL_IOFIC_MAX_GROUPS);
226 return al_reg_read32(®s->ctrl[group].int_cause_grp);
230 * clear bits in the interrupt cause register for a given group
232 void al_iofic_clear_cause(void __iomem *regs_base, int group, uint32_t mask)
234 struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
236 al_assert(regs_base);
237 al_assert(group < AL_IOFIC_MAX_GROUPS);
239 /* inverse mask, writing 1 has no effect */
240 al_reg_write32(®s->ctrl[group].int_cause_grp, ~mask);
244 * Set the cause register for a given group
246 void al_iofic_set_cause(void __iomem *regs_base, int group, uint32_t mask)
248 struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
250 al_assert(regs_base);
251 al_assert(group < AL_IOFIC_MAX_GROUPS);
253 al_reg_write32(®s->ctrl[group].int_cause_set_grp, mask);
258 * unmask specific interrupts from aborting the udma a given group
260 void al_iofic_abort_mask(void __iomem *regs_base, int group, uint32_t mask)
262 struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
264 al_assert(regs_base);
265 al_assert(group < AL_IOFIC_MAX_GROUPS);
267 al_reg_write32(®s->ctrl[group].int_abort_msk_grp, mask);
272 * trigger all interrupts that are waiting for moderation timers to expire
274 void al_iofic_interrupt_moderation_reset(void __iomem *regs_base, int group)
276 struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
279 al_assert(regs_base);
280 al_assert(group < AL_IOFIC_MAX_GROUPS);
282 al_assert(regs_base);
283 al_assert(group < AL_IOFIC_MAX_GROUPS);
285 reg = al_reg_read32(®s->ctrl[group].int_control_grp);
286 reg |= INT_CONTROL_GRP_MOD_RST;
288 al_reg_write32(®s->ctrl[group].int_control_grp, reg);
291 /** @} end of interrupt controller group */