Skip to content

[DM/feature] Implement PIC irq state { get; set } #9006

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions components/drivers/include/drivers/pic.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ struct rt_pic_ops
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);

#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);
rt_err_t (*irq_parse)(struct rt_pic *pic, struct rt_ofw_cell_args *args, struct rt_pic_irq *out_pirq);

Expand Down Expand Up @@ -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);
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_disable(struct rt_pic_irq *pirq);
void rt_pic_irq_parent_ack(struct rt_pic_irq *pirq);
Expand Down
66 changes: 66 additions & 0 deletions components/drivers/pic/pic-gicv2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
int irq, irq_index = hwirq - GIC_SGI_NR;
Expand Down Expand Up @@ -353,6 +417,8 @@ const static struct rt_pic_ops gicv2_ops =
.irq_set_affinity = gicv2_irq_set_affinity,
.irq_set_triger_mode = gicv2_irq_set_triger_mode,
.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_parse = gicv2_irq_parse,
};
Expand Down
83 changes: 83 additions & 0 deletions components/drivers/pic/pic-gicv3.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

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)
{
rt_uint32_t index;
Expand Down Expand Up @@ -600,6 +608,79 @@ static void gicv3_irq_send_ipi(struct rt_pic_irq *pirq, rt_bitmap_t *cpumask)
#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)
{
struct rt_pic_irq *pirq;
Expand Down Expand Up @@ -716,6 +797,8 @@ const static struct rt_pic_ops gicv3_ops =
.irq_set_affinity = gicv3_irq_set_affinity,
.irq_set_triger_mode = gicv3_irq_set_triger_mode,
.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_parse = gicv3_irq_parse,
};
Expand Down
79 changes: 79 additions & 0 deletions components/drivers/pic/pic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
RT_ASSERT(pirq != RT_NULL);
Expand Down
Loading