summaryrefslogtreecommitdiff
path: root/components/drivers/pic
diff options
context:
space:
mode:
authorguo <[email protected]>2023-07-06 16:52:30 +0800
committerGitHub <[email protected]>2023-07-06 16:52:30 +0800
commit78867912c114966d49e003db2ffb3407a5017b46 (patch)
treee8b34c99bbf57feb4e1e976993d01ef6f9d3fd13 /components/drivers/pic
parentc7be260665c9c753b343141968755d47deadd753 (diff)
parentfa10a99c3ccecd6113d30842a05e1b853cf7d1cb (diff)
Merge pull request #7788 from ErikChanHub/master
【dd2.0】Support Open Firmware API
Diffstat (limited to 'components/drivers/pic')
-rwxr-xr-xcomponents/drivers/pic/Kconfig11
-rw-r--r--components/drivers/pic/SConscript15
-rw-r--r--components/drivers/pic/pic.c977
3 files changed, 1003 insertions, 0 deletions
diff --git a/components/drivers/pic/Kconfig b/components/drivers/pic/Kconfig
new file mode 100755
index 0000000000..cadb52b669
--- /dev/null
+++ b/components/drivers/pic/Kconfig
@@ -0,0 +1,11 @@
+menuconfig RT_USING_PIC
+ bool "Using Programmable Interrupt Controller (PIC)"
+ select RT_USING_BITMAP
+ depends on RT_USING_DM
+ default n
+
+config MAX_HANDLERS
+ int "IRQ max handlers"
+ depends on RT_USING_PIC
+ range 1 4294967294
+ default 256
diff --git a/components/drivers/pic/SConscript b/components/drivers/pic/SConscript
new file mode 100644
index 0000000000..ade23fc309
--- /dev/null
+++ b/components/drivers/pic/SConscript
@@ -0,0 +1,15 @@
+from building import *
+
+group = []
+
+if not GetDepend(['RT_USING_PIC']):
+ Return('group')
+
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+src = ['pic.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/components/drivers/pic/pic.c b/components/drivers/pic/pic.c
new file mode 100644
index 0000000000..e5bc0fed7c
--- /dev/null
+++ b/components/drivers/pic/pic.c
@@ -0,0 +1,977 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-08-24 GuEe-GUI first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+
+#define DBG_TAG "rtdm.pic"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <drivers/pic.h>
+
+struct irq_traps
+{
+ rt_list_t list;
+
+ void *data;
+ rt_bool_t (*handler)(void *);
+};
+
+static int _ipi_hash[] =
+{
+#ifdef RT_USING_SMP
+ [RT_SCHEDULE_IPI] = RT_SCHEDULE_IPI,
+ [RT_STOP_IPI] = RT_STOP_IPI,
+#endif
+};
+
+/* reserved ipi */
+static int _pirq_hash_idx = RT_ARRAY_SIZE(_ipi_hash);
+static struct rt_pic_irq _pirq_hash[MAX_HANDLERS] =
+{
+ [0 ... MAX_HANDLERS - 1] =
+ {
+ .irq = -1,
+ .hwirq = -1,
+ .mode = RT_IRQ_MODE_NONE,
+ .priority = RT_UINT32_MAX,
+ .rw_lock = { },
+ }
+};
+
+static struct rt_spinlock _pic_lock = { };
+static rt_size_t _pic_name_max = sizeof("PIC");
+static rt_list_t _pic_nodes = RT_LIST_OBJECT_INIT(_pic_nodes);
+static rt_list_t _traps_nodes = RT_LIST_OBJECT_INIT(_traps_nodes);
+
+static struct rt_pic_irq *irq2pirq(int irq)
+{
+ struct rt_pic_irq *pirq;
+
+ if (irq >= 0 && irq < MAX_HANDLERS)
+ {
+ pirq = &_pirq_hash[irq];
+
+ if (pirq->irq < 0)
+ {
+ pirq = RT_NULL;
+ }
+ }
+
+ if (!pirq)
+ {
+ LOG_E("irq = %d is invalid", irq);
+ }
+
+ return pirq;
+}
+
+static void append_pic(struct rt_pic *pic)
+{
+ int pic_name_len = rt_strlen(pic->ops->name);
+
+ rt_list_insert_before(&_pic_nodes, &pic->list);
+
+ if (pic_name_len > _pic_name_max)
+ {
+ _pic_name_max = pic_name_len;
+ }
+}
+
+rt_err_t rt_pic_linear_irq(struct rt_pic *pic, rt_size_t irq_nr)
+{
+ rt_err_t err = RT_EOK;
+
+ if (pic && pic->ops && pic->ops->name)
+ {
+ rt_ubase_t level = rt_spin_lock_irqsave(&_pic_lock);
+
+ if (_pirq_hash_idx + irq_nr <= RT_ARRAY_SIZE(_pirq_hash))
+ {
+ rt_list_init(&pic->list);
+
+ pic->irq_start = _pirq_hash_idx;
+ pic->irq_nr = irq_nr;
+ pic->pirqs = &_pirq_hash[_pirq_hash_idx];
+
+ _pirq_hash_idx += irq_nr;
+
+ append_pic(pic);
+
+ LOG_D("%s alloc irqs ranges [%d, %d]", pic->ops->name,
+ pic->irq_start, pic->irq_start + pic->irq_nr);
+ }
+ else
+ {
+ LOG_E("%s alloc %d irqs is overflow", pic->ops->name, irq_nr);
+
+ err = -RT_EEMPTY;
+ }
+
+ rt_spin_unlock_irqrestore(&_pic_lock, level);
+ }
+ else
+ {
+ err = -RT_EINVAL;
+ }
+
+ return err;
+}
+
+static void config_pirq(struct rt_pic *pic, struct rt_pic_irq *pirq, int irq, int hwirq)
+{
+ rt_ubase_t level = rt_spin_lock_irqsave(&pirq->rw_lock);
+
+ pirq->irq = irq;
+ pirq->hwirq = hwirq;
+
+ pirq->pic = pic;
+
+ rt_list_init(&pirq->isr.list);
+
+ rt_spin_unlock_irqrestore(&pirq->rw_lock, level);
+}
+
+int rt_pic_config_ipi(struct rt_pic *pic, int ipi_index, int hwirq)
+{
+ int ipi = ipi_index;
+
+ if (pic && ipi < RT_ARRAY_SIZE(_ipi_hash) && hwirq >= 0 && pic->ops->irq_send_ipi)
+ {
+ config_pirq(pic, &_pirq_hash[ipi], ipi, hwirq);
+
+ LOG_D("%s config %s %d to hwirq %d", pic->ops->name, "ipi", ipi, hwirq);
+ }
+ else
+ {
+ ipi = -RT_EINVAL;
+ }
+
+ return ipi;
+}
+
+int rt_pic_config_irq(struct rt_pic *pic, int irq_index, int hwirq)
+{
+ int irq;
+
+ if (pic && hwirq >= 0)
+ {
+ irq = pic->irq_start + irq_index;
+
+ if (irq >= 0 && irq < MAX_HANDLERS)
+ {
+ config_pirq(pic, &_pirq_hash[irq], irq, hwirq);
+
+ LOG_D("%s config %s %d to hwirq %d", pic->ops->name, "irq", irq, hwirq);
+ }
+ else
+ {
+ irq = -RT_ERROR;
+ }
+ }
+ else
+ {
+ irq = -RT_EINVAL;
+ }
+
+ return irq;
+}
+
+struct rt_pic_irq *rt_pic_find_ipi(struct rt_pic *pic, int ipi_index)
+{
+ struct rt_pic_irq *pirq = &_pirq_hash[ipi_index];
+
+ RT_ASSERT(ipi_index < RT_ARRAY_SIZE(_ipi_hash));
+ RT_ASSERT(pirq->pic == pic);
+
+ return pirq;
+}
+
+int rt_pic_cascade(struct rt_pic *pic, struct rt_pic *parent_pic, int hwirq, rt_uint32_t mode)
+{
+ int irq = -RT_EINVAL;
+
+ if (pic && parent_pic && hwirq >= 0)
+ {
+ struct rt_pic *ppic = parent_pic;
+ rt_ubase_t level = rt_spin_lock_irqsave(&_pic_lock);
+
+ while (!ppic->ops->irq_map && ppic->parent)
+ {
+ ppic = ppic->parent;
+ }
+
+ rt_spin_unlock_irqrestore(&_pic_lock, level);
+
+ if (ppic->ops->irq_map)
+ {
+ struct rt_pic_irq *pirq;
+
+ irq = ppic->ops->irq_map(ppic, hwirq, mode);
+
+ if (irq >= 0 && (pirq = irq2pirq(irq)))
+ {
+ rt_spin_lock(&pirq->rw_lock);
+
+ pirq->pic = pic;
+ pic->parent = parent_pic;
+
+ rt_spin_unlock(&pirq->rw_lock);
+
+ if (rt_list_isempty(&pic->list))
+ {
+ rt_ubase_t level = rt_spin_lock_irqsave(&_pic_lock);
+
+ append_pic(pic);
+
+ rt_spin_unlock_irqrestore(&_pic_lock, level);
+ }
+ }
+ }
+ else
+ {
+ irq = -RT_ENOSYS;
+ }
+ }
+
+ return irq;
+}
+
+void rt_pic_uncascade(struct rt_pic *pic, int irq)
+{
+ struct rt_pic_irq *pirq;
+
+ if (pic && pic->parent && irq >= 0 && (pirq = irq2pirq(irq)))
+ {
+ struct rt_pic *ppic, *prev = RT_NULL;
+
+ rt_spin_lock(&pirq->rw_lock);
+
+ ppic = pirq->pic;
+
+ while (ppic && pic->parent != ppic->parent)
+ {
+ prev = ppic;
+ ppic = ppic->parent;
+ }
+
+ if (ppic)
+ {
+ if (prev)
+ {
+ pirq->pic = prev;
+ prev->parent = pic->parent;
+ }
+ else
+ {
+ pirq->pic = pic->parent;
+ }
+
+ pic->parent = RT_NULL;
+ }
+
+ rt_spin_unlock(&pirq->rw_lock);
+ }
+}
+
+rt_err_t rt_pic_attach_irq(int irq, rt_isr_handler_t handler, void *uid, const char *name, int flags)
+{
+ rt_err_t err = -RT_EINVAL;
+ struct rt_pic_irq *pirq;
+
+ if (handler && name && (pirq = irq2pirq(irq)))
+ {
+ struct rt_pic_isr *isr = RT_NULL;
+ rt_ubase_t level = rt_spin_lock_irqsave(&pirq->rw_lock);
+
+ err = RT_EOK;
+
+ if (!pirq->isr.action.handler)
+ {
+ /* first attach */
+ isr = &pirq->isr;
+ rt_list_init(&isr->list);
+ }
+ else
+ {
+ rt_spin_unlock_irqrestore(&pirq->rw_lock, level);
+
+ if ((isr = rt_malloc(sizeof(*isr))))
+ {
+ rt_list_init(&isr->list);
+
+ level = rt_spin_lock_irqsave(&pirq->rw_lock);
+
+ rt_list_insert_after(&pirq->isr.list, &isr->list);
+ }
+ else
+ {
+ LOG_E("No memory to save '%s' isr", name);
+ err = -RT_ERROR;
+ }
+ }
+
+ if (!err)
+ {
+ isr->flags = flags;
+ isr->action.handler = handler;
+ isr->action.param = uid;
+ #ifdef RT_USING_INTERRUPT_INFO
+ isr->action.counter = 0;
+ rt_strncpy(isr->action.name, name, RT_NAME_MAX);
+ #endif
+
+ rt_spin_unlock_irqrestore(&pirq->rw_lock, level);
+ }
+ }
+
+ return err;
+}
+
+rt_err_t rt_pic_detach_irq(int irq, void *uid)
+{
+ rt_err_t err = -RT_EINVAL;
+ struct rt_pic_irq *pirq = irq2pirq(irq);
+
+ if (pirq)
+ {
+ rt_bool_t will_free = RT_FALSE;
+ struct rt_pic_isr *isr = RT_NULL;
+ rt_ubase_t level = rt_spin_lock_irqsave(&pirq->rw_lock);
+
+ isr = &pirq->isr;
+
+ if (isr->action.param == uid)
+ {
+ if (rt_list_isempty(&isr->list))
+ {
+ isr->action.handler = RT_NULL;
+ isr->action.param = RT_NULL;
+ }
+ else
+ {
+ struct rt_pic_isr *next_isr = rt_list_entry(isr->list.next, struct rt_pic_isr, list);
+
+ rt_list_remove(&next_isr->list);
+
+ isr->action.handler = next_isr->action.handler;
+ isr->action.param = next_isr->action.param;
+ #ifdef RT_USING_INTERRUPT_INFO
+ isr->action.counter = next_isr->action.counter;
+ rt_strncpy(isr->action.name, next_isr->action.name, RT_NAME_MAX);
+ #endif
+
+ isr = next_isr;
+ will_free = RT_TRUE;
+ }
+
+ err = RT_EOK;
+ }
+ else
+ {
+ rt_list_for_each_entry(isr, &pirq->isr.list, list)
+ {
+ if (isr->action.param == uid)
+ {
+ err = RT_EOK;
+
+ will_free = RT_TRUE;
+ rt_list_remove(&isr->list);
+ break;
+ }
+ }
+ }
+
+ rt_spin_unlock_irqrestore(&pirq->rw_lock, level);
+
+ if (will_free)
+ {
+ rt_free(isr);
+ }
+ }
+
+ return err;
+}
+
+rt_err_t rt_pic_add_traps(rt_bool_t (*handler)(void *), void *data)
+{
+ rt_err_t err = -RT_EINVAL;
+
+ if (handler)
+ {
+ struct irq_traps *traps = rt_malloc(sizeof(*traps));
+
+ if (traps)
+ {
+ rt_ubase_t level = rt_hw_interrupt_disable();
+
+ rt_list_init(&traps->list);
+
+ traps->data = data;
+ traps->handler = handler;
+
+ rt_list_insert_before(&_traps_nodes, &traps->list);
+ err = RT_EOK;
+
+ rt_hw_interrupt_enable(level);
+ }
+ else
+ {
+ LOG_E("No memory to save '%p' handler", handler);
+ err = -RT_ENOMEM;
+ }
+ }
+
+ return err;
+}
+
+rt_err_t rt_pic_do_traps(void)
+{
+ rt_err_t err = -RT_ERROR;
+ struct irq_traps *traps;
+
+ rt_list_for_each_entry(traps, &_traps_nodes, list)
+ {
+ if (traps->handler(traps->data))
+ {
+ err = RT_EOK;
+
+ break;
+ }
+ }
+
+ return err;
+}
+
+rt_err_t rt_pic_handle_isr(struct rt_pic_irq *pirq)
+{
+ rt_err_t err;
+ rt_list_t *handler_nodes;
+ struct rt_irq_desc *action;
+
+ RT_ASSERT(pirq != RT_NULL);
+ RT_ASSERT(pirq->pic != RT_NULL);
+
+ /* Corrected irq affinity */
+ rt_bitmap_set_bit(pirq->affinity, rt_hw_cpu_id());
+
+ handler_nodes = &pirq->isr.list;
+ action = &pirq->isr.action;
+
+ if (action->handler)
+ {
+ action->handler(pirq->irq, action->param);
+ #ifdef RT_USING_INTERRUPT_INFO
+ action->counter++;
+ #endif
+
+ if (!rt_list_isempty(handler_nodes))
+ {
+ struct rt_pic_isr *isr;
+
+ rt_list_for_each_entry(isr, handler_nodes, list)
+ {
+ action = &isr->action;
+
+ RT_ASSERT(action->handler != RT_NULL);
+
+ action->handler(pirq->irq, action->param);
+ #ifdef RT_USING_INTERRUPT_INFO
+ action->counter++;
+ #endif
+ }
+ }
+ }
+ else
+ {
+ err = -RT_EEMPTY;
+ }
+
+ return err;
+}
+
+rt_weak rt_err_t rt_pic_user_extends(struct rt_pic *pic)
+{
+ return -RT_ENOSYS;
+}
+
+rt_err_t rt_pic_irq_init(void)
+{
+ rt_err_t err = RT_EOK;
+ struct rt_pic *pic;
+
+ rt_list_for_each_entry(pic, &_pic_nodes, list)
+ {
+ if (pic->ops->irq_init)
+ {
+ err = pic->ops->irq_init(pic);
+
+ if (err)
+ {
+ LOG_E("PIC = %s init fail", pic->ops->name);
+ break;
+ }
+ }
+ }
+
+ return err;
+}
+
+rt_err_t rt_pic_irq_finit(void)
+{
+ rt_err_t err = RT_EOK;
+ struct rt_pic *pic;
+
+ rt_list_for_each_entry(pic, &_pic_nodes, list)
+ {
+ if (pic->ops->irq_finit)
+ {
+ err = pic->ops->irq_finit(pic);
+
+ if (err)
+ {
+ LOG_E("PIC = %s finit fail", pic->ops->name);
+ break;
+ }
+ }
+ }
+
+ return err;
+}
+
+#define _irq_call_helper(irq, fn) \
+({ \
+ struct rt_pic_irq *pirq; \
+ if ((pirq = irq2pirq(irq))) \
+ { \
+ rt_spin_lock(&pirq->rw_lock); \
+ if (pirq->pic->ops->fn) \
+ pirq->pic->ops->fn(pirq); \
+ rt_spin_unlock(&pirq->rw_lock); \
+ } \
+})
+
+void rt_pic_irq_enable(int irq)
+{
+ _irq_call_helper(irq, irq_enable);
+}
+
+void rt_pic_irq_disable(int irq)
+{
+ _irq_call_helper(irq, irq_disable);
+}
+
+void rt_pic_irq_ack(int irq)
+{
+ _irq_call_helper(irq, irq_ack);
+}
+
+void rt_pic_irq_mask(int irq)
+{
+ _irq_call_helper(irq, irq_mask);
+}
+
+void rt_pic_irq_unmask(int irq)
+{
+ _irq_call_helper(irq, irq_unmask);
+}
+
+void rt_pic_irq_eoi(int irq)
+{
+ _irq_call_helper(irq, irq_eoi);
+}
+
+#undef _irq_call_helper
+
+rt_err_t rt_pic_irq_set_priority(int irq, rt_uint32_t priority)
+{
+ rt_err_t err = -RT_EINVAL;
+ struct rt_pic_irq *pirq = irq2pirq(irq);
+
+ if (pirq)
+ {
+ rt_spin_lock(&pirq->rw_lock);
+
+ if (pirq->pic->ops->irq_set_priority)
+ {
+ err = pirq->pic->ops->irq_set_priority(pirq, priority);
+
+ if (!err)
+ {
+ pirq->priority = priority;
+ }
+ }
+ else
+ {
+ err = -RT_ENOSYS;
+ }
+
+ rt_spin_unlock(&pirq->rw_lock);
+ }
+
+ return err;
+}
+
+rt_uint32_t rt_pic_irq_get_priority(int irq)
+{
+ rt_uint32_t priority = RT_UINT32_MAX;
+ struct rt_pic_irq *pirq = irq2pirq(irq);
+
+ if (pirq)
+ {
+ rt_spin_lock(&pirq->rw_lock);
+
+ priority = pirq->priority;
+
+ rt_spin_unlock(&pirq->rw_lock);
+ }
+
+ return priority;
+}
+
+rt_err_t rt_pic_irq_set_affinity(int irq, rt_bitmap_t *affinity)
+{
+ rt_err_t err = -RT_EINVAL;
+ struct rt_pic_irq *pirq;
+
+ if (affinity && (pirq = irq2pirq(irq)))
+ {
+ rt_spin_lock(&pirq->rw_lock);
+
+ if (pirq->pic->ops->irq_set_affinity)
+ {
+ err = pirq->pic->ops->irq_set_affinity(pirq, affinity);
+
+ if (!err)
+ {
+ rt_memcpy(pirq->affinity, affinity, sizeof(pirq->affinity));
+ }
+ }
+ else
+ {
+ err = -RT_ENOSYS;
+ }
+
+ rt_spin_unlock(&pirq->rw_lock);
+ }
+
+ return err;
+}
+
+rt_err_t rt_pic_irq_get_affinity(int irq, rt_bitmap_t *out_affinity)
+{
+ rt_err_t err = -RT_EINVAL;
+ struct rt_pic_irq *pirq;
+
+ if (out_affinity && (pirq = irq2pirq(irq)))
+ {
+ rt_spin_lock(&pirq->rw_lock);
+
+ rt_memcpy(out_affinity, pirq->affinity, sizeof(pirq->affinity));
+ err = RT_EOK;
+
+ rt_spin_unlock(&pirq->rw_lock);
+ }
+
+ return err;
+}
+
+rt_err_t rt_pic_irq_set_triger_mode(int irq, rt_uint32_t mode)
+{
+ rt_err_t err = -RT_EINVAL;
+ struct rt_pic_irq *pirq;
+
+ if ((~mode & RT_IRQ_MODE_MASK) && (pirq = irq2pirq(irq)))
+ {
+ rt_spin_lock(&pirq->rw_lock);
+
+ if (pirq->pic->ops->irq_set_triger_mode)
+ {
+ err = pirq->pic->ops->irq_set_triger_mode(pirq, mode);
+
+ if (!err)
+ {
+ pirq->mode = mode;
+ }
+ }
+ else
+ {
+ err = -RT_ENOSYS;
+ }
+
+ rt_spin_unlock(&pirq->rw_lock);
+ }
+
+ return err;
+}
+
+rt_uint32_t rt_pic_irq_get_triger_mode(int irq)
+{
+ rt_uint32_t mode = RT_UINT32_MAX;
+ struct rt_pic_irq *pirq = irq2pirq(irq);
+
+ if (pirq)
+ {
+ rt_spin_lock(&pirq->rw_lock);
+
+ mode = pirq->mode;
+
+ rt_spin_unlock(&pirq->rw_lock);
+ }
+
+ return mode;
+}
+
+void rt_pic_irq_send_ipi(int irq, rt_bitmap_t *cpumask)
+{
+ struct rt_pic_irq *pirq;
+
+ if (cpumask && (pirq = irq2pirq(irq)))
+ {
+ rt_hw_spin_lock(&pirq->rw_lock.lock);
+
+ if (pirq->pic->ops->irq_send_ipi)
+ {
+ pirq->pic->ops->irq_send_ipi(pirq, cpumask);
+ }
+
+ rt_hw_spin_unlock(&pirq->rw_lock.lock);
+ }
+}
+
+#define _pirq_parent_call_helper(ppic, pirq, fn, ret,...) \
+({ \
+ if (ppic && pirq) \
+ { \
+ rt_spin_lock(&pirq->rw_lock); \
+ if (ppic->ops->fn) \
+ { \
+ struct rt_pic *cpic; \
+ cpic = pirq->pic; /* push old pic */ \
+ pirq->pic = ppic; \
+ ret ppic->ops->fn(pirq __VA_ARGS__); \
+ pirq->pic = cpic; /* pop old pic */ \
+ } \
+ rt_spin_unlock(&pirq->rw_lock); \
+ } \
+})
+
+void rt_pic_irq_parent_enable(struct rt_pic *ppic, struct rt_pic_irq *pirq)
+{
+ _pirq_parent_call_helper(ppic, pirq, irq_enable,,);
+}
+
+void rt_pic_irq_parent_disable(struct rt_pic *ppic, struct rt_pic_irq *pirq)
+{
+ _pirq_parent_call_helper(ppic, pirq, irq_disable,,);
+}
+
+void rt_pic_irq_parent_ack(struct rt_pic *ppic, struct rt_pic_irq *pirq)
+{
+ _pirq_parent_call_helper(ppic, pirq, irq_ack,,);
+}
+
+void rt_pic_irq_parent_mask(struct rt_pic *ppic, struct rt_pic_irq *pirq)
+{
+ _pirq_parent_call_helper(ppic, pirq, irq_mask,,);
+}
+
+void rt_pic_irq_parent_unmask(struct rt_pic *ppic, struct rt_pic_irq *pirq)
+{
+ _pirq_parent_call_helper(ppic, pirq, irq_unmask,,);
+}
+
+void rt_pic_irq_parent_eoi(struct rt_pic *ppic, struct rt_pic_irq *pirq)
+{
+ _pirq_parent_call_helper(ppic, pirq, irq_eoi,,);
+}
+
+rt_err_t rt_pic_irq_parent_set_priority(struct rt_pic *ppic, struct rt_pic_irq *pirq, rt_uint32_t priority)
+{
+ rt_err_t err = -RT_ENOSYS;
+
+ _pirq_parent_call_helper(ppic, pirq, irq_set_priority, err = , ,priority);
+
+ return err;
+}
+
+rt_err_t rt_pic_irq_parent_set_affinity(struct rt_pic *ppic, struct rt_pic_irq *pirq, rt_bitmap_t *affinity)
+{
+ rt_err_t err = -RT_ENOSYS;
+
+ _pirq_parent_call_helper(ppic, pirq, irq_set_affinity, err = , ,affinity);
+
+ return err;
+}
+
+rt_err_t rt_pic_irq_parent_set_triger_mode(struct rt_pic *ppic, struct rt_pic_irq *pirq, rt_uint32_t mode)
+{
+ rt_err_t err = -RT_ENOSYS;
+
+ _pirq_parent_call_helper(ppic, pirq, irq_set_triger_mode, err = , ,mode);
+
+ return err;
+}
+
+#undef _pirq_parent_call_helper
+
+#ifdef RT_USING_OFW
+RT_OFW_STUB_RANGE_EXPORT(pic, _pic_ofw_start, _pic_ofw_end);
+
+static rt_err_t ofw_pic_init(void)
+{
+ struct rt_ofw_node *ic_np;
+
+ rt_ofw_foreach_node_by_prop(ic_np, "interrupt-controller")
+ {
+ rt_ofw_stub_probe_range(ic_np, &_pic_ofw_start, &_pic_ofw_end);
+ }
+
+ return RT_EOK;
+}
+#else
+static rt_err_t ofw_pic_init(void)
+{
+ return RT_EOK;
+}
+#endif /* !RT_USING_OFW */
+
+rt_err_t rt_pic_init(void)
+{
+ rt_err_t err;
+
+ LOG_D("init start");
+
+ err = ofw_pic_init();
+
+ LOG_D("init end");
+
+ return err;
+}
+
+#if defined(RT_USING_CONSOLE) && defined(RT_USING_MSH)
+static int list_irq(int argc, char**argv)
+{
+ rt_ubase_t level;
+ rt_size_t irq_nr = 0;
+ rt_bool_t dump_all = RT_FALSE;
+ const char *const irq_modes[] =
+ {
+ [RT_IRQ_MODE_NONE] = "None",
+ [RT_IRQ_MODE_EDGE_RISING] = "Edge-Rising",
+ [RT_IRQ_MODE_EDGE_FALLING] = "Edge-Falling",
+ [RT_IRQ_MODE_EDGE_BOTH] = "Edge-Both",
+ [RT_IRQ_MODE_LEVEL_HIGH] = "Level-High",
+ [RT_IRQ_MODE_LEVEL_LOW] = "Level-Low",
+ };
+ static char info[RT_CONSOLEBUF_SIZE];
+#ifdef RT_USING_SMP
+ static char cpumask[RT_CPUS_NR + 1] = { [RT_CPUS_NR] = '\0' };
+#endif
+
+ if (argc > 1)
+ {
+ if (!rt_strcmp(argv[1], "all"))
+ {
+ dump_all = RT_TRUE;
+ }
+ }
+
+ level = rt_hw_interrupt_disable();
+
+ rt_kprintf("%-*.s %-*.s %s %-*.s %-*.s %-*.s %-*.sUsers%s\n",
+ 10, "IRQ",
+ 10, "HW-IRQ",
+ "MSI",
+ _pic_name_max, "PIC",
+ 12, "Mode",
+ #ifdef RT_USING_SMP
+ RT_CPUS_NR, "CPUs",
+ #else
+ 0, 0,
+ #endif
+ #ifdef RT_USING_INTERRUPT_INFO
+ 11, "Count",
+ ""
+ #else
+ 0, 0,
+ "-Number"
+ #endif
+ );
+
+ for (int i = 0; i < RT_ARRAY_SIZE(_pirq_hash); ++i)
+ {
+ struct rt_pic_irq *pirq = &_pirq_hash[i];
+
+ if (!pirq->pic || !(dump_all || pirq->isr.action.handler))
+ {
+ continue;
+ }
+
+ rt_snprintf(info, sizeof(info), "%-10d %-10d %c %-*.s %-*.s ",
+ pirq->irq,
+ pirq->hwirq,
+ pirq->msi_desc ? 'Y' : 'N',
+ _pic_name_max, pirq->pic->ops->name,
+ 12, irq_modes[pirq->mode]);
+
+ #ifdef RT_USING_SMP
+ for (int group = 0, id = 0; group < RT_ARRAY_SIZE(pirq->affinity); ++group)
+ {
+ rt_bitmap_t mask = pirq->affinity[group];
+
+ for (int idx = 0; id < RT_CPUS_NR && idx < BITMAP_BIT_LEN(1); ++idx, ++id)
+ {
+ cpumask[RT_ARRAY_SIZE(cpumask) - id - 2] = '0' + ((mask >> idx) & 1);
+ }
+ }
+ #endif /* RT_USING_SMP */
+
+ rt_kputs(info);
+ #ifdef RT_USING_SMP
+ rt_kputs(cpumask);
+ #endif
+
+ #ifdef RT_USING_INTERRUPT_INFO
+ rt_kprintf(" %-10d ", pirq->isr.action.counter);
+ rt_kputs(pirq->isr.action.name);
+ rt_kputs("\n");
+
+ if (!rt_list_isempty(&pirq->isr.list))
+ {
+ struct rt_pic_isr *repeat_isr;
+
+ rt_list_for_each_entry(repeat_isr, &pirq->isr.list, list)
+ {
+ rt_kputs(info);
+ #ifdef RT_USING_SMP
+ rt_kputs(cpumask);
+ #endif
+ rt_kprintf("%-10d ", repeat_isr->action.counter);
+ rt_kputs(repeat_isr->action.name);
+ rt_kputs("\n");
+ }
+ }
+ #else
+ rt_kprintf(" %d\n", rt_list_len(&pirq->isr.list));
+ #endif
+
+ ++irq_nr;
+ }
+
+ rt_hw_interrupt_enable(level);
+
+ rt_kprintf("%d IRQs found\n", irq_nr);
+
+ return 0;
+}
+MSH_CMD_EXPORT(list_irq, dump using or args = all of irq information);
+#endif /* RT_USING_CONSOLE && RT_USING_MSH */