Lines Matching +full:group +full:- +full:index +full:- +full:shift
1 // SPDX-License-Identifier: GPL-2.0
12 #include <linux/irqchip/riscv-aplic.h>
13 #include <linux/irqchip/riscv-imsic.h>
21 #include "irq-riscv-aplic-main.h"
43 * The section "4.9.2 Special consideration for level-sensitive interrupt in aplic_msi_irq_retrigger_level()
44 * sources" of the RISC-V AIA specification says: in aplic_msi_irq_retrigger_level()
52 writel(d->hwirq, priv->regs + APLIC_SETIPNUM_LE); in aplic_msi_irq_retrigger_level()
60 * EOI handling is required only for level-triggered interrupts in aplic_msi_irq_eoi()
73 * Updating sourcecfg register for level-triggered interrupts in aplic_msi_irq_set_type()
84 struct aplic_msicfg *mc = &priv->msicfg; in aplic_msi_write_msg()
89 if (!msg->address_hi && !msg->address_lo && !msg->data) { in aplic_msi_write_msg()
90 target = priv->regs + APLIC_TARGET_BASE; in aplic_msi_write_msg()
91 target += (d->hwirq - 1) * sizeof(u32); in aplic_msi_write_msg()
97 WARN_ON(msg->data > APLIC_TARGET_EIID_MASK); in aplic_msi_write_msg()
100 msg_addr = (((u64)msg->address_hi) << 32) | msg->address_lo; in aplic_msi_write_msg()
105 tbppn &= ~APLIC_xMSICFGADDR_PPN_HART(mc->lhxs); in aplic_msi_write_msg()
106 tbppn &= ~APLIC_xMSICFGADDR_PPN_LHX(mc->lhxw, mc->lhxs); in aplic_msi_write_msg()
107 tbppn &= ~APLIC_xMSICFGADDR_PPN_HHX(mc->hhxw, mc->hhxs); in aplic_msi_write_msg()
108 WARN_ON(tbppn != mc->base_ppn); in aplic_msi_write_msg()
110 /* Compute target group and hart indexes */ in aplic_msi_write_msg()
111 group_index = (tppn >> APLIC_xMSICFGADDR_PPN_HHX_SHIFT(mc->hhxs)) & in aplic_msi_write_msg()
112 APLIC_xMSICFGADDR_PPN_HHX_MASK(mc->hhxw); in aplic_msi_write_msg()
113 hart_index = (tppn >> APLIC_xMSICFGADDR_PPN_LHX_SHIFT(mc->lhxs)) & in aplic_msi_write_msg()
114 APLIC_xMSICFGADDR_PPN_LHX_MASK(mc->lhxw); in aplic_msi_write_msg()
115 hart_index |= (group_index << mc->lhxw); in aplic_msi_write_msg()
118 /* Compute target guest index */ in aplic_msi_write_msg()
119 guest_index = tppn & APLIC_xMSICFGADDR_PPN_HART(mc->lhxs); in aplic_msi_write_msg()
123 target = priv->regs + APLIC_TARGET_BASE; in aplic_msi_write_msg()
124 target += (d->hwirq - 1) * sizeof(u32); in aplic_msi_write_msg()
127 val |= FIELD_PREP(APLIC_TARGET_EIID, msg->data); in aplic_msi_write_msg()
133 arg->desc = desc; in aplic_msi_set_desc()
134 arg->hwirq = (u32)desc->data.icookie.value; in aplic_msi_set_desc()
140 struct msi_domain_info *info = d->host_data; in aplic_msi_translate()
141 struct aplic_priv *priv = info->data; in aplic_msi_translate()
143 return aplic_irqdomain_translate(fwspec, priv->gsi_base, hwirq, type); in aplic_msi_translate()
148 .name = "APLIC-MSI",
186 return -ENOMEM; in aplic_msi_setup()
193 mc = &priv->msicfg; in aplic_msi_setup()
197 * controller to be RISC-V AIA IMSIC controller. in aplic_msi_setup()
202 return -ENODEV; in aplic_msi_setup()
205 /* Find number of guest index bits (LHXS) */ in aplic_msi_setup()
206 mc->lhxs = imsic_global->guest_index_bits; in aplic_msi_setup()
207 if (APLIC_xMSICFGADDRH_LHXS_MASK < mc->lhxs) { in aplic_msi_setup()
208 dev_err(dev, "IMSIC guest index bits big for APLIC LHXS\n"); in aplic_msi_setup()
209 return -EINVAL; in aplic_msi_setup()
212 /* Find number of HART index bits (LHXW) */ in aplic_msi_setup()
213 mc->lhxw = imsic_global->hart_index_bits; in aplic_msi_setup()
214 if (APLIC_xMSICFGADDRH_LHXW_MASK < mc->lhxw) { in aplic_msi_setup()
215 dev_err(dev, "IMSIC hart index bits big for APLIC LHXW\n"); in aplic_msi_setup()
216 return -EINVAL; in aplic_msi_setup()
219 /* Find number of group index bits (HHXW) */ in aplic_msi_setup()
220 mc->hhxw = imsic_global->group_index_bits; in aplic_msi_setup()
221 if (APLIC_xMSICFGADDRH_HHXW_MASK < mc->hhxw) { in aplic_msi_setup()
222 dev_err(dev, "IMSIC group index bits big for APLIC HHXW\n"); in aplic_msi_setup()
223 return -EINVAL; in aplic_msi_setup()
226 /* Find first bit position of group index (HHXS) */ in aplic_msi_setup()
227 mc->hhxs = imsic_global->group_index_shift; in aplic_msi_setup()
228 if (mc->hhxs < (2 * APLIC_xMSICFGADDR_PPN_SHIFT)) { in aplic_msi_setup()
229 dev_err(dev, "IMSIC group index shift should be >= %d\n", in aplic_msi_setup()
231 return -EINVAL; in aplic_msi_setup()
233 mc->hhxs -= (2 * APLIC_xMSICFGADDR_PPN_SHIFT); in aplic_msi_setup()
234 if (APLIC_xMSICFGADDRH_HHXS_MASK < mc->hhxs) { in aplic_msi_setup()
235 dev_err(dev, "IMSIC group index shift big for APLIC HHXS\n"); in aplic_msi_setup()
236 return -EINVAL; in aplic_msi_setup()
240 mc->base_ppn = imsic_global->base_addr >> APLIC_xMSICFGADDR_PPN_SHIFT; in aplic_msi_setup()
241 mc->base_ppn &= ~APLIC_xMSICFGADDR_PPN_HART(mc->lhxs); in aplic_msi_setup()
242 mc->base_ppn &= ~APLIC_xMSICFGADDR_PPN_LHX(mc->lhxw, mc->lhxs); in aplic_msi_setup()
243 mc->base_ppn &= ~APLIC_xMSICFGADDR_PPN_HHX(mc->hhxw, mc->hhxs); in aplic_msi_setup()
261 if (is_of_node(dev->fwnode)) { in aplic_msi_setup()
262 of_msi_configure(dev, to_of_node(dev->fwnode)); in aplic_msi_setup()
272 priv->nr_irqs + 1, priv, priv)) { in aplic_msi_setup()
274 return -ENOMEM; in aplic_msi_setup()
278 pa = priv->msicfg.base_ppn << APLIC_xMSICFGADDR_PPN_SHIFT; in aplic_msi_setup()
279 dev_info(dev, "%d interrupts forwarded to MSI base %pa\n", priv->nr_irqs, &pa); in aplic_msi_setup()