1294838Szbb/*- 2294838Szbb******************************************************************************* 3294838SzbbCopyright (C) 2015 Annapurna Labs Ltd. 4294838Szbb 5294838SzbbThis file may be licensed under the terms of the Annapurna Labs Commercial 6294838SzbbLicense Agreement. 7294838Szbb 8294838SzbbAlternatively, this file can be distributed under the terms of the GNU General 9294838SzbbPublic License V2 as published by the Free Software Foundation and can be 10294838Szbbfound at http://www.gnu.org/licenses/gpl-2.0.html 11294838Szbb 12294838SzbbAlternatively, redistribution and use in source and binary forms, with or 13294838Szbbwithout modification, are permitted provided that the following conditions are 14294838Szbbmet: 15294838Szbb 16294838Szbb * Redistributions of source code must retain the above copyright notice, 17294838Szbbthis list of conditions and the following disclaimer. 18294838Szbb 19294838Szbb * Redistributions in binary form must reproduce the above copyright 20294838Szbbnotice, this list of conditions and the following disclaimer in 21294838Szbbthe documentation and/or other materials provided with the 22294838Szbbdistribution. 23294838Szbb 24294838SzbbTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 25294838SzbbANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26294838SzbbWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27294838SzbbDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 28294838SzbbANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29294838Szbb(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30294838SzbbLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 31294838SzbbANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32294838Szbb(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33294838SzbbSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34294838Szbb 35294838Szbb*******************************************************************************/ 36294838Szbb 37294838Szbb/** 38294838Szbb * @{ 39294838Szbb * @file al_hal_iofic.c 40294838Szbb * 41294838Szbb * @brief interrupt controller hal 42294838Szbb * 43294838Szbb */ 44294838Szbb 45294838Szbb#include "al_hal_iofic.h" 46294838Szbb#include "al_hal_iofic_regs.h" 47294838Szbb 48294838Szbb/* 49294838Szbb * configure the interrupt registers, interrupts will are kept masked 50294838Szbb */ 51294838Szbbint al_iofic_config(void __iomem *regs_base, int group, uint32_t flags) 52294838Szbb{ 53294838Szbb struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); 54294838Szbb 55294838Szbb al_assert(regs_base); 56294838Szbb al_assert(group < AL_IOFIC_MAX_GROUPS); 57294838Szbb 58294838Szbb al_reg_write32(®s->ctrl[group].int_control_grp, flags); 59294838Szbb 60294838Szbb return 0; 61294838Szbb} 62294838Szbb 63294838Szbb/* 64294838Szbb * configure the moderation timer resolution for a given group 65294838Szbb */ 66294838Szbbint al_iofic_moder_res_config(void __iomem *regs_base, int group, 67294838Szbb uint8_t resolution) 68294838Szbb 69294838Szbb{ 70294838Szbb struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); 71294838Szbb uint32_t reg; 72294838Szbb 73294838Szbb al_assert(regs_base); 74294838Szbb al_assert(group < AL_IOFIC_MAX_GROUPS); 75294838Szbb 76294838Szbb reg = al_reg_read32(®s->ctrl[group].int_control_grp); 77294838Szbb AL_REG_FIELD_SET(reg, 78294838Szbb INT_CONTROL_GRP_MOD_RES_MASK, 79294838Szbb INT_CONTROL_GRP_MOD_RES_SHIFT, 80294838Szbb resolution); 81294838Szbb al_reg_write32(®s->ctrl[group].int_control_grp, reg); 82294838Szbb 83294838Szbb return 0; 84294838Szbb} 85294838Szbb 86294838Szbb/* 87294838Szbb * configure the moderation timer interval for a given legacy interrupt group 88294838Szbb */ 89294838Szbbint al_iofic_legacy_moder_interval_config(void __iomem *regs_base, int group, 90294838Szbb uint8_t interval) 91294838Szbb{ 92294838Szbb struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); 93294838Szbb uint32_t reg; 94294838Szbb 95294838Szbb al_assert(regs_base); 96294838Szbb al_assert(group < AL_IOFIC_MAX_GROUPS); 97294838Szbb 98294838Szbb reg = al_reg_read32(®s->ctrl[group].int_control_grp); 99294838Szbb AL_REG_FIELD_SET(reg, 100294838Szbb INT_CONTROL_GRP_MOD_INTV_MASK, 101294838Szbb INT_CONTROL_GRP_MOD_INTV_SHIFT, 102294838Szbb interval); 103294838Szbb al_reg_write32(®s->ctrl[group].int_control_grp, reg); 104294838Szbb 105294838Szbb return 0; 106294838Szbb} 107294838Szbb 108294838Szbb 109294838Szbb/* 110294838Szbb * configure the moderation timer interval for a given msix vector. 111294838Szbb */ 112294838Szbbint al_iofic_msix_moder_interval_config(void __iomem *regs_base, int group, 113294838Szbb uint8_t vector, uint8_t interval) 114294838Szbb{ 115294838Szbb struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); 116294838Szbb uint32_t reg; 117294838Szbb 118294838Szbb al_assert(regs_base); 119294838Szbb al_assert(group < AL_IOFIC_MAX_GROUPS); 120294838Szbb 121294838Szbb reg = al_reg_read32(®s->grp_int_mod[group][vector].grp_int_mod_reg); 122294838Szbb AL_REG_FIELD_SET(reg, 123294838Szbb INT_MOD_INTV_MASK, 124294838Szbb INT_MOD_INTV_SHIFT, 125294838Szbb interval); 126294838Szbb al_reg_write32(®s->grp_int_mod[group][vector].grp_int_mod_reg, reg); 127294838Szbb 128294838Szbb return 0; 129294838Szbb} 130294838Szbb 131294838Szbb/* 132294838Szbb * configure the vmid attributes for a given msix vector. 133294838Szbb */ 134294838Szbbint al_iofic_msix_vmid_attributes_config(void __iomem *regs_base, int group, 135294838Szbb uint8_t vector, uint32_t vmid, uint8_t vmid_en) 136294838Szbb{ 137294838Szbb struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); 138294838Szbb uint32_t reg = 0; 139294838Szbb 140294838Szbb al_assert(regs_base); 141294838Szbb al_assert(group < AL_IOFIC_MAX_GROUPS); 142294838Szbb 143294838Szbb AL_REG_FIELD_SET(reg, 144294838Szbb INT_MSIX_VMID_MASK, 145294838Szbb INT_MSIX_VMID_SHIFT, 146294838Szbb vmid); 147294838Szbb AL_REG_BIT_VAL_SET(reg, 148294838Szbb INT_MSIX_VMID_EN_SHIFT, 149294838Szbb vmid_en); 150294838Szbb 151294838Szbb al_reg_write32(®s->grp_int_mod[group][vector].grp_int_vmid_reg, reg); 152294838Szbb 153294838Szbb return 0; 154294838Szbb} 155294838Szbb 156294838Szbb/* 157294838Szbb * return the offset of the unmask register for a given group 158294838Szbb */ 159294838Szbbuint32_t __iomem * al_iofic_unmask_offset_get(void __iomem *regs_base, int group) 160294838Szbb{ 161294838Szbb struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); 162294838Szbb 163294838Szbb al_assert(regs_base); 164294838Szbb al_assert(group < AL_IOFIC_MAX_GROUPS); 165294838Szbb 166294838Szbb return ®s->ctrl[group].int_mask_clear_grp; 167294838Szbb} 168294838Szbb 169294838Szbb 170294838Szbb/* 171294838Szbb * unmask specific interrupts for a given group 172294838Szbb */ 173294838Szbbvoid al_iofic_unmask(void __iomem *regs_base, int group, uint32_t mask) 174294838Szbb{ 175294838Szbb struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); 176294838Szbb 177294838Szbb al_assert(regs_base); 178294838Szbb al_assert(group < AL_IOFIC_MAX_GROUPS); 179294838Szbb 180294838Szbb /* 181294838Szbb * use the mask clear register, no need to read the mask register 182294838Szbb * itself. write 0 to unmask, 1 has no effect 183294838Szbb */ 184294838Szbb al_reg_write32_relaxed(®s->ctrl[group].int_mask_clear_grp, ~mask); 185294838Szbb} 186294838Szbb 187294838Szbb/* 188294838Szbb * mask specific interrupts for a given group 189294838Szbb */ 190294838Szbbvoid al_iofic_mask(void __iomem *regs_base, int group, uint32_t mask) 191294838Szbb{ 192294838Szbb struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); 193294838Szbb uint32_t reg; 194294838Szbb 195294838Szbb al_assert(regs_base); 196294838Szbb al_assert(group < AL_IOFIC_MAX_GROUPS); 197294838Szbb 198294838Szbb reg = al_reg_read32(®s->ctrl[group].int_mask_grp); 199294838Szbb 200294838Szbb al_reg_write32(®s->ctrl[group].int_mask_grp, reg | mask); 201294838Szbb} 202294838Szbb 203294838Szbb/* 204294838Szbb * read the mask for a given group 205294838Szbb */ 206294838Szbbuint32_t al_iofic_read_mask(void __iomem *regs_base, int group) 207294838Szbb{ 208294838Szbb struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); 209294838Szbb 210294838Szbb al_assert(regs_base); 211294838Szbb al_assert(group < AL_IOFIC_MAX_GROUPS); 212294838Szbb 213294838Szbb return al_reg_read32(®s->ctrl[group].int_mask_grp); 214294838Szbb} 215294838Szbb 216294838Szbb/* 217294838Szbb * read interrupt cause register for a given group 218294838Szbb */ 219294838Szbbuint32_t al_iofic_read_cause(void __iomem *regs_base, int group) 220294838Szbb{ 221294838Szbb struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); 222294838Szbb 223294838Szbb al_assert(regs_base); 224294838Szbb al_assert(group < AL_IOFIC_MAX_GROUPS); 225294838Szbb 226294838Szbb return al_reg_read32(®s->ctrl[group].int_cause_grp); 227294838Szbb} 228294838Szbb 229294838Szbb/* 230294838Szbb * clear bits in the interrupt cause register for a given group 231294838Szbb */ 232294838Szbbvoid al_iofic_clear_cause(void __iomem *regs_base, int group, uint32_t mask) 233294838Szbb{ 234294838Szbb struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); 235294838Szbb 236294838Szbb al_assert(regs_base); 237294838Szbb al_assert(group < AL_IOFIC_MAX_GROUPS); 238294838Szbb 239294838Szbb /* inverse mask, writing 1 has no effect */ 240294838Szbb al_reg_write32(®s->ctrl[group].int_cause_grp, ~mask); 241294838Szbb} 242294838Szbb 243294838Szbb/* 244294838Szbb * Set the cause register for a given group 245294838Szbb */ 246294838Szbbvoid al_iofic_set_cause(void __iomem *regs_base, int group, uint32_t mask) 247294838Szbb{ 248294838Szbb struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); 249294838Szbb 250294838Szbb al_assert(regs_base); 251294838Szbb al_assert(group < AL_IOFIC_MAX_GROUPS); 252294838Szbb 253294838Szbb al_reg_write32(®s->ctrl[group].int_cause_set_grp, mask); 254294838Szbb} 255294838Szbb 256294838Szbb 257294838Szbb/* 258294838Szbb * unmask specific interrupts from aborting the udma a given group 259294838Szbb */ 260294838Szbbvoid al_iofic_abort_mask(void __iomem *regs_base, int group, uint32_t mask) 261294838Szbb{ 262294838Szbb struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); 263294838Szbb 264294838Szbb al_assert(regs_base); 265294838Szbb al_assert(group < AL_IOFIC_MAX_GROUPS); 266294838Szbb 267294838Szbb al_reg_write32(®s->ctrl[group].int_abort_msk_grp, mask); 268294838Szbb 269294838Szbb} 270294838Szbb 271294838Szbb/* 272294838Szbb * trigger all interrupts that are waiting for moderation timers to expire 273294838Szbb */ 274294838Szbbvoid al_iofic_interrupt_moderation_reset(void __iomem *regs_base, int group) 275294838Szbb{ 276294838Szbb struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); 277294838Szbb uint32_t reg = 0; 278294838Szbb 279294838Szbb al_assert(regs_base); 280294838Szbb al_assert(group < AL_IOFIC_MAX_GROUPS); 281294838Szbb 282294838Szbb al_assert(regs_base); 283294838Szbb al_assert(group < AL_IOFIC_MAX_GROUPS); 284294838Szbb 285294838Szbb reg = al_reg_read32(®s->ctrl[group].int_control_grp); 286294838Szbb reg |= INT_CONTROL_GRP_MOD_RST; 287294838Szbb 288294838Szbb al_reg_write32(®s->ctrl[group].int_control_grp, reg); 289294838Szbb} 290294838Szbb 291294838Szbb/** @} end of interrupt controller group */ 292