writel_gicd(1U << (irqd->irq % 32), offset + (irqd->irq / 32) * 4);
}
+/*
+ * This is forcing the active state of an interrupt, somewhat circumventing
+ * the normal interrupt flow and the GIC state machine. So use with care
+ * and only if you know what you are doing. For this reason we also have to
+ * tinker with the _IRQ_INPROGRESS bit here, since the normal IRQ handler
+ * will not be involved.
+ */
+static void gicv2_set_active_state(struct irq_desc *irqd, bool active)
+{
+ ASSERT(spin_is_locked(&irqd->lock));
+
+ if ( active )
+ {
+ set_bit(_IRQ_INPROGRESS, &irqd->status);
+ gicv2_poke_irq(irqd, GICD_ISACTIVER);
+ }
+ else
+ {
+ clear_bit(_IRQ_INPROGRESS, &irqd->status);
+ gicv2_poke_irq(irqd, GICD_ICACTIVER);
+ }
+}
+
+static void gicv2_set_pending_state(struct irq_desc *irqd, bool pending)
+{
+ ASSERT(spin_is_locked(&irqd->lock));
+
+ if ( pending )
+ {
+ /* The _IRQ_INPROGRESS bit will be set when the interrupt fires. */
+ gicv2_poke_irq(irqd, GICD_ISPENDR);
+ }
+ else
+ {
+ /* The _IRQ_INPROGRESS remains unchanged. */
+ gicv2_poke_irq(irqd, GICD_ICPENDR);
+ }
+}
+
static void gicv2_set_irq_type(struct irq_desc *desc, unsigned int type)
{
uint32_t cfg, actual, edgebit;
.eoi_irq = gicv2_eoi_irq,
.deactivate_irq = gicv2_dir_irq,
.read_irq = gicv2_read_irq,
+ .set_active_state = gicv2_set_active_state,
+ .set_pending_state = gicv2_set_pending_state,
.set_irq_type = gicv2_set_irq_type,
.set_irq_priority = gicv2_set_irq_priority,
.send_SGI = gicv2_send_SGI,
return irq;
}
+/*
+ * This is forcing the active state of an interrupt, somewhat circumventing
+ * the normal interrupt flow and the GIC state machine. So use with care
+ * and only if you know what you are doing. For this reason we also have to
+ * tinker with the _IRQ_INPROGRESS bit here, since the normal IRQ handler
+ * will not be involved.
+ */
+static void gicv3_set_active_state(struct irq_desc *irqd, bool active)
+{
+ ASSERT(spin_is_locked(&irqd->lock));
+
+ if ( active )
+ {
+ set_bit(_IRQ_INPROGRESS, &irqd->status);
+ gicv3_poke_irq(irqd, GICD_ISACTIVER, false);
+ }
+ else
+ {
+ clear_bit(_IRQ_INPROGRESS, &irqd->status);
+ gicv3_poke_irq(irqd, GICD_ICACTIVER, false);
+ }
+}
+
+static void gicv3_set_pending_state(struct irq_desc *irqd, bool pending)
+{
+ ASSERT(spin_is_locked(&irqd->lock));
+
+ if ( pending )
+ /* The _IRQ_INPROGRESS bit will be set when the interrupt fires. */
+ gicv3_poke_irq(irqd, GICD_ISPENDR, false);
+ else
+ /* The _IRQ_INPROGRESS bit will remain unchanged. */
+ gicv3_poke_irq(irqd, GICD_ICPENDR, false);
+}
+
static inline uint64_t gicv3_mpidr_to_affinity(int cpu)
{
uint64_t mpidr = cpu_logical_map(cpu);
.eoi_irq = gicv3_eoi_irq,
.deactivate_irq = gicv3_dir_irq,
.read_irq = gicv3_read_irq,
+ .set_active_state = gicv3_set_active_state,
+ .set_pending_state = gicv3_set_pending_state,
.set_irq_type = gicv3_set_irq_type,
.set_irq_priority = gicv3_set_irq_priority,
.send_SGI = gicv3_send_sgi,
void (*deactivate_irq)(struct irq_desc *irqd);
/* Read IRQ id and Ack */
unsigned int (*read_irq)(void);
+ /* Force the active state of an IRQ by accessing the distributor */
+ void (*set_active_state)(struct irq_desc *irqd, bool state);
+ /* Force the pending state of an IRQ by accessing the distributor */
+ void (*set_pending_state)(struct irq_desc *irqd, bool state);
/* Set IRQ type */
void (*set_irq_type)(struct irq_desc *desc, unsigned int type);
/* Set IRQ priority */
return gic_hw_ops->info->nr_lrs;
}
+/*
+ * Set the active state of an IRQ. This should be used with care, as this
+ * directly forces the active bit, without considering the GIC state machine.
+ * For private IRQs this only works for those of the current CPU.
+ */
+static inline void gic_set_active_state(struct irq_desc *irqd, bool state)
+{
+ gic_hw_ops->set_active_state(irqd, state);
+}
+
+/*
+ * Set the pending state of an IRQ. This should be used with care, as this
+ * directly forces the pending bit, without considering the GIC state machine.
+ * For private IRQs this only works for those of the current CPU.
+ */
+static inline void gic_set_pending_state(struct irq_desc *irqd, bool state)
+{
+ gic_hw_ops->set_pending_state(irqd, state);
+}
+
void register_gic_ops(const struct gic_hw_operations *ops);
int gic_make_hwdom_dt_node(const struct domain *d,
const struct dt_device_node *gic,