[DM/feature] Implement PIC irq state { get; set } (#9006)
* [DM/feature] Implement PIC irq state { get; set } There are some common state for irq: 1. Pending: IRQ was triggered, but software not ACK. 2. Active: IRQ was ACK, but not EOI. 3. Masked: IRQ was masked or umasked. Signed-off-by: GuEe-GUI <2991707448@qq.com> * [DM/pic] Support IRQ state { get; set } for ARM GICv2/v3 Signed-off-by: GuEe-GUI <2991707448@qq.com> --------- Signed-off-by: GuEe-GUI <2991707448@qq.com>
This commit is contained in:
parent
aa81fd4a88
commit
1d614a819d
|
@ -75,6 +75,12 @@ struct rt_pic_ops
|
||||||
int (*irq_alloc_msi)(struct rt_pic *pic, struct rt_pci_msi_desc *msi_desc);
|
int (*irq_alloc_msi)(struct rt_pic *pic, struct rt_pci_msi_desc *msi_desc);
|
||||||
void (*irq_free_msi)(struct rt_pic *pic, int irq);
|
void (*irq_free_msi)(struct rt_pic *pic, int irq);
|
||||||
|
|
||||||
|
#define RT_IRQ_STATE_PENDING 0
|
||||||
|
#define RT_IRQ_STATE_ACTIVE 1
|
||||||
|
#define RT_IRQ_STATE_MASKED 2
|
||||||
|
rt_err_t (*irq_set_state)(struct rt_pic *pic, int hwirq, int type, rt_bool_t state);
|
||||||
|
rt_err_t (*irq_get_state)(struct rt_pic *pic, int hwirq, int type, rt_bool_t *out_state);
|
||||||
|
|
||||||
int (*irq_map)(struct rt_pic *pic, int hwirq, rt_uint32_t mode);
|
int (*irq_map)(struct rt_pic *pic, int hwirq, rt_uint32_t mode);
|
||||||
rt_err_t (*irq_parse)(struct rt_pic *pic, struct rt_ofw_cell_args *args, struct rt_pic_irq *out_pirq);
|
rt_err_t (*irq_parse)(struct rt_pic *pic, struct rt_ofw_cell_args *args, struct rt_pic_irq *out_pirq);
|
||||||
|
|
||||||
|
@ -189,6 +195,11 @@ rt_err_t rt_pic_irq_set_triger_mode(int irq, rt_uint32_t mode);
|
||||||
rt_uint32_t rt_pic_irq_get_triger_mode(int irq);
|
rt_uint32_t rt_pic_irq_get_triger_mode(int irq);
|
||||||
void rt_pic_irq_send_ipi(int irq, rt_bitmap_t *cpumask);
|
void rt_pic_irq_send_ipi(int irq, rt_bitmap_t *cpumask);
|
||||||
|
|
||||||
|
rt_err_t rt_pic_irq_set_state_raw(struct rt_pic *pic, int hwirq, int type, rt_bool_t state);
|
||||||
|
rt_err_t rt_pic_irq_get_state_raw(struct rt_pic *pic, int hwirq, int type, rt_bool_t *out_state);
|
||||||
|
rt_err_t rt_pic_irq_set_state(int irq, int type, rt_bool_t state);
|
||||||
|
rt_err_t rt_pic_irq_get_state(int irq, int type, rt_bool_t *out_state);
|
||||||
|
|
||||||
void rt_pic_irq_parent_enable(struct rt_pic_irq *pirq);
|
void rt_pic_irq_parent_enable(struct rt_pic_irq *pirq);
|
||||||
void rt_pic_irq_parent_disable(struct rt_pic_irq *pirq);
|
void rt_pic_irq_parent_disable(struct rt_pic_irq *pirq);
|
||||||
void rt_pic_irq_parent_ack(struct rt_pic_irq *pirq);
|
void rt_pic_irq_parent_ack(struct rt_pic_irq *pirq);
|
||||||
|
|
|
@ -276,6 +276,70 @@ static void gicv2_irq_send_ipi(struct rt_pic_irq *pirq, rt_bitmap_t *cpumask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static rt_err_t gicv2_irq_set_state(struct rt_pic *pic, int hwirq, int type, rt_bool_t state)
|
||||||
|
{
|
||||||
|
rt_err_t err = RT_EOK;
|
||||||
|
rt_uint32_t offset = 0;
|
||||||
|
struct gicv2 *gic = raw_to_gicv2(pic);
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case RT_IRQ_STATE_PENDING:
|
||||||
|
offset = state ? GIC_DIST_PENDING_SET : GIC_DIST_PENDING_CLEAR;
|
||||||
|
break;
|
||||||
|
case RT_IRQ_STATE_ACTIVE:
|
||||||
|
offset = state ? GIC_DIST_ACTIVE_SET : GIC_DIST_ACTIVE_CLEAR;
|
||||||
|
break;
|
||||||
|
case RT_IRQ_STATE_MASKED:
|
||||||
|
offset = state ? GIC_DIST_ENABLE_CLEAR : GIC_DIST_ENABLE_SET;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err = -RT_EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
rt_uint32_t mask = 1 << (hwirq % 32);
|
||||||
|
|
||||||
|
HWREG32(gic->dist_base + offset + (hwirq / 32) * 4) = mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t gicv2_irq_get_state(struct rt_pic *pic, int hwirq, int type, rt_bool_t *out_state)
|
||||||
|
{
|
||||||
|
rt_err_t err = RT_EOK;
|
||||||
|
rt_uint32_t offset = 0;
|
||||||
|
struct gicv2 *gic = raw_to_gicv2(pic);
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case RT_IRQ_STATE_PENDING:
|
||||||
|
offset = GIC_DIST_PENDING_SET;
|
||||||
|
break;
|
||||||
|
case RT_IRQ_STATE_ACTIVE:
|
||||||
|
offset = GIC_DIST_ACTIVE_SET;
|
||||||
|
break;
|
||||||
|
case RT_IRQ_STATE_MASKED:
|
||||||
|
offset = GIC_DIST_ENABLE_SET;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err = -RT_EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
rt_uint32_t mask = 1 << (hwirq % 32);
|
||||||
|
|
||||||
|
*out_state = !!(HWREG32(gic->dist_base + offset + (hwirq / 32) * 4) & mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int gicv2_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode)
|
static int gicv2_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode)
|
||||||
{
|
{
|
||||||
int irq, irq_index = hwirq - GIC_SGI_NR;
|
int irq, irq_index = hwirq - GIC_SGI_NR;
|
||||||
|
@ -353,6 +417,8 @@ const static struct rt_pic_ops gicv2_ops =
|
||||||
.irq_set_affinity = gicv2_irq_set_affinity,
|
.irq_set_affinity = gicv2_irq_set_affinity,
|
||||||
.irq_set_triger_mode = gicv2_irq_set_triger_mode,
|
.irq_set_triger_mode = gicv2_irq_set_triger_mode,
|
||||||
.irq_send_ipi = gicv2_irq_send_ipi,
|
.irq_send_ipi = gicv2_irq_send_ipi,
|
||||||
|
.irq_set_state = gicv2_irq_set_state,
|
||||||
|
.irq_get_state = gicv2_irq_get_state,
|
||||||
.irq_map = gicv2_irq_map,
|
.irq_map = gicv2_irq_map,
|
||||||
.irq_parse = gicv2_irq_parse,
|
.irq_parse = gicv2_irq_parse,
|
||||||
};
|
};
|
||||||
|
|
|
@ -187,6 +187,14 @@ static void *gicv3_hwirq_reg_base(int hwirq, rt_uint32_t offset, rt_uint32_t *in
|
||||||
return base + gicv3_hwirq_convert_offset_index(hwirq, offset, index);
|
return base + gicv3_hwirq_convert_offset_index(hwirq, offset, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static rt_bool_t gicv3_hwirq_peek(int hwirq, rt_uint32_t offset)
|
||||||
|
{
|
||||||
|
rt_uint32_t index;
|
||||||
|
void *base = gicv3_hwirq_reg_base(hwirq, offset, &index);
|
||||||
|
|
||||||
|
return !!HWREG32(base + (index / 32) * 4);
|
||||||
|
}
|
||||||
|
|
||||||
static void gicv3_hwirq_poke(int hwirq, rt_uint32_t offset)
|
static void gicv3_hwirq_poke(int hwirq, rt_uint32_t offset)
|
||||||
{
|
{
|
||||||
rt_uint32_t index;
|
rt_uint32_t index;
|
||||||
|
@ -600,6 +608,79 @@ static void gicv3_irq_send_ipi(struct rt_pic_irq *pirq, rt_bitmap_t *cpumask)
|
||||||
#undef __mpidr_to_sgi_affinity
|
#undef __mpidr_to_sgi_affinity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static rt_err_t gicv3_irq_set_state(struct rt_pic *pic, int hwirq, int type, rt_bool_t state)
|
||||||
|
{
|
||||||
|
rt_err_t err = RT_EOK;
|
||||||
|
rt_uint32_t offset = 0;
|
||||||
|
|
||||||
|
if (hwirq >= 8192)
|
||||||
|
{
|
||||||
|
type = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case RT_IRQ_STATE_PENDING:
|
||||||
|
offset = state ? GICD_ISPENDR : GICD_ICPENDR;
|
||||||
|
break;
|
||||||
|
case RT_IRQ_STATE_ACTIVE:
|
||||||
|
offset = state ? GICD_ISACTIVER : GICD_ICACTIVER;
|
||||||
|
break;
|
||||||
|
case RT_IRQ_STATE_MASKED:
|
||||||
|
if (state)
|
||||||
|
{
|
||||||
|
struct rt_pic_irq pirq = {};
|
||||||
|
|
||||||
|
pirq.hwirq = hwirq;
|
||||||
|
gicv3_irq_mask(&pirq);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
offset = GICD_ISENABLER;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err = -RT_EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!err && offset)
|
||||||
|
{
|
||||||
|
gicv3_hwirq_poke(hwirq, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t gicv3_irq_get_state(struct rt_pic *pic, int hwirq, int type, rt_bool_t *out_state)
|
||||||
|
{
|
||||||
|
rt_err_t err = RT_EOK;
|
||||||
|
rt_uint32_t offset = 0;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case RT_IRQ_STATE_PENDING:
|
||||||
|
offset = GICD_ISPENDR;
|
||||||
|
break;
|
||||||
|
case RT_IRQ_STATE_ACTIVE:
|
||||||
|
offset = GICD_ISACTIVER;
|
||||||
|
break;
|
||||||
|
case RT_IRQ_STATE_MASKED:
|
||||||
|
offset = GICD_ISENABLER;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err = -RT_EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
*out_state = gicv3_hwirq_peek(hwirq, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int gicv3_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode)
|
static int gicv3_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode)
|
||||||
{
|
{
|
||||||
struct rt_pic_irq *pirq;
|
struct rt_pic_irq *pirq;
|
||||||
|
@ -716,6 +797,8 @@ const static struct rt_pic_ops gicv3_ops =
|
||||||
.irq_set_affinity = gicv3_irq_set_affinity,
|
.irq_set_affinity = gicv3_irq_set_affinity,
|
||||||
.irq_set_triger_mode = gicv3_irq_set_triger_mode,
|
.irq_set_triger_mode = gicv3_irq_set_triger_mode,
|
||||||
.irq_send_ipi = gicv3_irq_send_ipi,
|
.irq_send_ipi = gicv3_irq_send_ipi,
|
||||||
|
.irq_set_state = gicv3_irq_set_state,
|
||||||
|
.irq_get_state = gicv3_irq_get_state,
|
||||||
.irq_map = gicv3_irq_map,
|
.irq_map = gicv3_irq_map,
|
||||||
.irq_parse = gicv3_irq_parse,
|
.irq_parse = gicv3_irq_parse,
|
||||||
};
|
};
|
||||||
|
|
|
@ -893,6 +893,85 @@ void rt_pic_irq_send_ipi(int irq, rt_bitmap_t *cpumask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rt_err_t rt_pic_irq_set_state_raw(struct rt_pic *pic, int hwirq, int type, rt_bool_t state)
|
||||||
|
{
|
||||||
|
rt_err_t err;
|
||||||
|
|
||||||
|
if (pic && hwirq >= 0)
|
||||||
|
{
|
||||||
|
if (pic->ops->irq_set_state)
|
||||||
|
{
|
||||||
|
err = pic->ops->irq_set_state(pic, hwirq, type, state);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err = -RT_ENOSYS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err = -RT_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
rt_err_t rt_pic_irq_get_state_raw(struct rt_pic *pic, int hwirq, int type, rt_bool_t *out_state)
|
||||||
|
{
|
||||||
|
rt_err_t err;
|
||||||
|
|
||||||
|
if (pic && hwirq >= 0)
|
||||||
|
{
|
||||||
|
if (pic->ops->irq_get_state)
|
||||||
|
{
|
||||||
|
rt_bool_t state;
|
||||||
|
|
||||||
|
if (!(err = pic->ops->irq_get_state(pic, hwirq, type, &state)) && out_state)
|
||||||
|
{
|
||||||
|
*out_state = state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err = -RT_ENOSYS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err = -RT_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
rt_err_t rt_pic_irq_set_state(int irq, int type, rt_bool_t state)
|
||||||
|
{
|
||||||
|
rt_err_t err;
|
||||||
|
struct rt_pic_irq *pirq = irq2pirq(irq);
|
||||||
|
|
||||||
|
RT_ASSERT(pirq != RT_NULL);
|
||||||
|
|
||||||
|
rt_hw_spin_lock(&pirq->rw_lock.lock);
|
||||||
|
err = rt_pic_irq_set_state_raw(pirq->pic, pirq->hwirq, type, state);
|
||||||
|
rt_hw_spin_unlock(&pirq->rw_lock.lock);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
rt_err_t rt_pic_irq_get_state(int irq, int type, rt_bool_t *out_state)
|
||||||
|
{
|
||||||
|
rt_err_t err;
|
||||||
|
struct rt_pic_irq *pirq = irq2pirq(irq);
|
||||||
|
|
||||||
|
RT_ASSERT(pirq != RT_NULL);
|
||||||
|
|
||||||
|
rt_hw_spin_lock(&pirq->rw_lock.lock);
|
||||||
|
err = rt_pic_irq_get_state_raw(pirq->pic, pirq->hwirq, type, out_state);
|
||||||
|
rt_hw_spin_unlock(&pirq->rw_lock.lock);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
void rt_pic_irq_parent_enable(struct rt_pic_irq *pirq)
|
void rt_pic_irq_parent_enable(struct rt_pic_irq *pirq)
|
||||||
{
|
{
|
||||||
RT_ASSERT(pirq != RT_NULL);
|
RT_ASSERT(pirq != RT_NULL);
|
||||||
|
|
Loading…
Reference in New Issue