Skip to content

Commit 1d614a8

Browse files
authored
[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 <[email protected]> * [DM/pic] Support IRQ state { get; set } for ARM GICv2/v3 Signed-off-by: GuEe-GUI <[email protected]> --------- Signed-off-by: GuEe-GUI <[email protected]>
1 parent aa81fd4 commit 1d614a8

File tree

4 files changed

+239
-0
lines changed

4 files changed

+239
-0
lines changed

components/drivers/include/drivers/pic.h

+11
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ struct rt_pic_ops
7575
int (*irq_alloc_msi)(struct rt_pic *pic, struct rt_pci_msi_desc *msi_desc);
7676
void (*irq_free_msi)(struct rt_pic *pic, int irq);
7777

78+
#define RT_IRQ_STATE_PENDING 0
79+
#define RT_IRQ_STATE_ACTIVE 1
80+
#define RT_IRQ_STATE_MASKED 2
81+
rt_err_t (*irq_set_state)(struct rt_pic *pic, int hwirq, int type, rt_bool_t state);
82+
rt_err_t (*irq_get_state)(struct rt_pic *pic, int hwirq, int type, rt_bool_t *out_state);
83+
7884
int (*irq_map)(struct rt_pic *pic, int hwirq, rt_uint32_t mode);
7985
rt_err_t (*irq_parse)(struct rt_pic *pic, struct rt_ofw_cell_args *args, struct rt_pic_irq *out_pirq);
8086

@@ -189,6 +195,11 @@ rt_err_t rt_pic_irq_set_triger_mode(int irq, rt_uint32_t mode);
189195
rt_uint32_t rt_pic_irq_get_triger_mode(int irq);
190196
void rt_pic_irq_send_ipi(int irq, rt_bitmap_t *cpumask);
191197

198+
rt_err_t rt_pic_irq_set_state_raw(struct rt_pic *pic, int hwirq, int type, rt_bool_t state);
199+
rt_err_t rt_pic_irq_get_state_raw(struct rt_pic *pic, int hwirq, int type, rt_bool_t *out_state);
200+
rt_err_t rt_pic_irq_set_state(int irq, int type, rt_bool_t state);
201+
rt_err_t rt_pic_irq_get_state(int irq, int type, rt_bool_t *out_state);
202+
192203
void rt_pic_irq_parent_enable(struct rt_pic_irq *pirq);
193204
void rt_pic_irq_parent_disable(struct rt_pic_irq *pirq);
194205
void rt_pic_irq_parent_ack(struct rt_pic_irq *pirq);

components/drivers/pic/pic-gicv2.c

+66
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,70 @@ static void gicv2_irq_send_ipi(struct rt_pic_irq *pirq, rt_bitmap_t *cpumask)
276276
}
277277
}
278278

279+
static rt_err_t gicv2_irq_set_state(struct rt_pic *pic, int hwirq, int type, rt_bool_t state)
280+
{
281+
rt_err_t err = RT_EOK;
282+
rt_uint32_t offset = 0;
283+
struct gicv2 *gic = raw_to_gicv2(pic);
284+
285+
switch (type)
286+
{
287+
case RT_IRQ_STATE_PENDING:
288+
offset = state ? GIC_DIST_PENDING_SET : GIC_DIST_PENDING_CLEAR;
289+
break;
290+
case RT_IRQ_STATE_ACTIVE:
291+
offset = state ? GIC_DIST_ACTIVE_SET : GIC_DIST_ACTIVE_CLEAR;
292+
break;
293+
case RT_IRQ_STATE_MASKED:
294+
offset = state ? GIC_DIST_ENABLE_CLEAR : GIC_DIST_ENABLE_SET;
295+
break;
296+
default:
297+
err = -RT_EINVAL;
298+
break;
299+
}
300+
301+
if (!err)
302+
{
303+
rt_uint32_t mask = 1 << (hwirq % 32);
304+
305+
HWREG32(gic->dist_base + offset + (hwirq / 32) * 4) = mask;
306+
}
307+
308+
return err;
309+
}
310+
311+
static rt_err_t gicv2_irq_get_state(struct rt_pic *pic, int hwirq, int type, rt_bool_t *out_state)
312+
{
313+
rt_err_t err = RT_EOK;
314+
rt_uint32_t offset = 0;
315+
struct gicv2 *gic = raw_to_gicv2(pic);
316+
317+
switch (type)
318+
{
319+
case RT_IRQ_STATE_PENDING:
320+
offset = GIC_DIST_PENDING_SET;
321+
break;
322+
case RT_IRQ_STATE_ACTIVE:
323+
offset = GIC_DIST_ACTIVE_SET;
324+
break;
325+
case RT_IRQ_STATE_MASKED:
326+
offset = GIC_DIST_ENABLE_SET;
327+
break;
328+
default:
329+
err = -RT_EINVAL;
330+
break;
331+
}
332+
333+
if (!err)
334+
{
335+
rt_uint32_t mask = 1 << (hwirq % 32);
336+
337+
*out_state = !!(HWREG32(gic->dist_base + offset + (hwirq / 32) * 4) & mask);
338+
}
339+
340+
return err;
341+
}
342+
279343
static int gicv2_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode)
280344
{
281345
int irq, irq_index = hwirq - GIC_SGI_NR;
@@ -353,6 +417,8 @@ const static struct rt_pic_ops gicv2_ops =
353417
.irq_set_affinity = gicv2_irq_set_affinity,
354418
.irq_set_triger_mode = gicv2_irq_set_triger_mode,
355419
.irq_send_ipi = gicv2_irq_send_ipi,
420+
.irq_set_state = gicv2_irq_set_state,
421+
.irq_get_state = gicv2_irq_get_state,
356422
.irq_map = gicv2_irq_map,
357423
.irq_parse = gicv2_irq_parse,
358424
};

components/drivers/pic/pic-gicv3.c

+83
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,14 @@ static void *gicv3_hwirq_reg_base(int hwirq, rt_uint32_t offset, rt_uint32_t *in
187187
return base + gicv3_hwirq_convert_offset_index(hwirq, offset, index);
188188
}
189189

190+
static rt_bool_t gicv3_hwirq_peek(int hwirq, rt_uint32_t offset)
191+
{
192+
rt_uint32_t index;
193+
void *base = gicv3_hwirq_reg_base(hwirq, offset, &index);
194+
195+
return !!HWREG32(base + (index / 32) * 4);
196+
}
197+
190198
static void gicv3_hwirq_poke(int hwirq, rt_uint32_t offset)
191199
{
192200
rt_uint32_t index;
@@ -600,6 +608,79 @@ static void gicv3_irq_send_ipi(struct rt_pic_irq *pirq, rt_bitmap_t *cpumask)
600608
#undef __mpidr_to_sgi_affinity
601609
}
602610

611+
static rt_err_t gicv3_irq_set_state(struct rt_pic *pic, int hwirq, int type, rt_bool_t state)
612+
{
613+
rt_err_t err = RT_EOK;
614+
rt_uint32_t offset = 0;
615+
616+
if (hwirq >= 8192)
617+
{
618+
type = -1;
619+
}
620+
621+
switch (type)
622+
{
623+
case RT_IRQ_STATE_PENDING:
624+
offset = state ? GICD_ISPENDR : GICD_ICPENDR;
625+
break;
626+
case RT_IRQ_STATE_ACTIVE:
627+
offset = state ? GICD_ISACTIVER : GICD_ICACTIVER;
628+
break;
629+
case RT_IRQ_STATE_MASKED:
630+
if (state)
631+
{
632+
struct rt_pic_irq pirq = {};
633+
634+
pirq.hwirq = hwirq;
635+
gicv3_irq_mask(&pirq);
636+
}
637+
else
638+
{
639+
offset = GICD_ISENABLER;
640+
}
641+
break;
642+
default:
643+
err = -RT_EINVAL;
644+
break;
645+
}
646+
647+
if (!err && offset)
648+
{
649+
gicv3_hwirq_poke(hwirq, offset);
650+
}
651+
652+
return err;
653+
}
654+
655+
static rt_err_t gicv3_irq_get_state(struct rt_pic *pic, int hwirq, int type, rt_bool_t *out_state)
656+
{
657+
rt_err_t err = RT_EOK;
658+
rt_uint32_t offset = 0;
659+
660+
switch (type)
661+
{
662+
case RT_IRQ_STATE_PENDING:
663+
offset = GICD_ISPENDR;
664+
break;
665+
case RT_IRQ_STATE_ACTIVE:
666+
offset = GICD_ISACTIVER;
667+
break;
668+
case RT_IRQ_STATE_MASKED:
669+
offset = GICD_ISENABLER;
670+
break;
671+
default:
672+
err = -RT_EINVAL;
673+
break;
674+
}
675+
676+
if (!err)
677+
{
678+
*out_state = gicv3_hwirq_peek(hwirq, offset);
679+
}
680+
681+
return err;
682+
}
683+
603684
static int gicv3_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode)
604685
{
605686
struct rt_pic_irq *pirq;
@@ -716,6 +797,8 @@ const static struct rt_pic_ops gicv3_ops =
716797
.irq_set_affinity = gicv3_irq_set_affinity,
717798
.irq_set_triger_mode = gicv3_irq_set_triger_mode,
718799
.irq_send_ipi = gicv3_irq_send_ipi,
800+
.irq_set_state = gicv3_irq_set_state,
801+
.irq_get_state = gicv3_irq_get_state,
719802
.irq_map = gicv3_irq_map,
720803
.irq_parse = gicv3_irq_parse,
721804
};

components/drivers/pic/pic.c

+79
Original file line numberDiff line numberDiff line change
@@ -893,6 +893,85 @@ void rt_pic_irq_send_ipi(int irq, rt_bitmap_t *cpumask)
893893
}
894894
}
895895

896+
rt_err_t rt_pic_irq_set_state_raw(struct rt_pic *pic, int hwirq, int type, rt_bool_t state)
897+
{
898+
rt_err_t err;
899+
900+
if (pic && hwirq >= 0)
901+
{
902+
if (pic->ops->irq_set_state)
903+
{
904+
err = pic->ops->irq_set_state(pic, hwirq, type, state);
905+
}
906+
else
907+
{
908+
err = -RT_ENOSYS;
909+
}
910+
}
911+
else
912+
{
913+
err = -RT_EINVAL;
914+
}
915+
916+
return err;
917+
}
918+
919+
rt_err_t rt_pic_irq_get_state_raw(struct rt_pic *pic, int hwirq, int type, rt_bool_t *out_state)
920+
{
921+
rt_err_t err;
922+
923+
if (pic && hwirq >= 0)
924+
{
925+
if (pic->ops->irq_get_state)
926+
{
927+
rt_bool_t state;
928+
929+
if (!(err = pic->ops->irq_get_state(pic, hwirq, type, &state)) && out_state)
930+
{
931+
*out_state = state;
932+
}
933+
}
934+
else
935+
{
936+
err = -RT_ENOSYS;
937+
}
938+
}
939+
else
940+
{
941+
err = -RT_EINVAL;
942+
}
943+
944+
return err;
945+
}
946+
947+
rt_err_t rt_pic_irq_set_state(int irq, int type, rt_bool_t state)
948+
{
949+
rt_err_t err;
950+
struct rt_pic_irq *pirq = irq2pirq(irq);
951+
952+
RT_ASSERT(pirq != RT_NULL);
953+
954+
rt_hw_spin_lock(&pirq->rw_lock.lock);
955+
err = rt_pic_irq_set_state_raw(pirq->pic, pirq->hwirq, type, state);
956+
rt_hw_spin_unlock(&pirq->rw_lock.lock);
957+
958+
return err;
959+
}
960+
961+
rt_err_t rt_pic_irq_get_state(int irq, int type, rt_bool_t *out_state)
962+
{
963+
rt_err_t err;
964+
struct rt_pic_irq *pirq = irq2pirq(irq);
965+
966+
RT_ASSERT(pirq != RT_NULL);
967+
968+
rt_hw_spin_lock(&pirq->rw_lock.lock);
969+
err = rt_pic_irq_get_state_raw(pirq->pic, pirq->hwirq, type, out_state);
970+
rt_hw_spin_unlock(&pirq->rw_lock.lock);
971+
972+
return err;
973+
}
974+
896975
void rt_pic_irq_parent_enable(struct rt_pic_irq *pirq)
897976
{
898977
RT_ASSERT(pirq != RT_NULL);

0 commit comments

Comments
 (0)