-
Notifications
You must be signed in to change notification settings - Fork 7k
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
[RFC] drivers: intc: plic: multi-instance support - approach 2 #62481
Conversation
598a30c
to
c9e14e4
Compare
002a64e
to
eb87551
Compare
cc @carlocaione |
eb87551
to
1044109
Compare
1044109
to
a5f21f9
Compare
7b438a1
to
bac14c6
Compare
@@ -5,6 +5,15 @@ | |||
|
|||
menu "Interrupt controller drivers" | |||
|
|||
config MULTI_INSTANCE_INTC |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't require a Kconfig - devicetree to describe hw, kconfig to describe sw
config MULTI_INSTANCE_INTC | ||
bool | ||
|
||
config HAS_MUTLI_INSTANCE_INTC |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this shouldn't require a kconfig
/** | ||
* @brief Enable interrupt | ||
* | ||
* @param irq interrupt ID | ||
*/ | ||
void riscv_plic_irq_enable(uint32_t irq); | ||
void riscv_plic_irq_enable(uint32_t irq, const struct device *dev); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The signature for this should probably not be changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this approach, the IRQN doesn't carry information about the plic instance, so the dev
is required
|
||
/** | ||
* @brief Disable interrupt | ||
* | ||
* @param irq interrupt ID | ||
*/ | ||
void riscv_plic_irq_disable(uint32_t irq); | ||
void riscv_plic_irq_disable(uint32_t irq, const struct device *dev); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the signature for this should probably not be changed.
|
||
/** | ||
* @brief Check if an interrupt is enabled | ||
* | ||
* @param irq interrupt ID | ||
* @return Returns true if interrupt is enabled, false otherwise | ||
*/ | ||
int riscv_plic_irq_is_enabled(uint32_t irq); | ||
int riscv_plic_irq_is_enabled(uint32_t irq, const struct device *dev); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the signature for this should probably not be changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as the irq
doesnt carry the interrupt controller info, an additional dev
arg is required in a multi-instance configuration
* | ||
* @return Returns the device struct of the interrupt controller | ||
*/ | ||
const struct device *riscv_plic_get_dev(void); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There can be multiple active interrupts on separate cores - is that taken into consideration here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SMP is not considered in this PR
@@ -48,6 +48,20 @@ extern "C" { | |||
#define IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \ | |||
ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) | |||
|
|||
#ifdef CONFIG_MULTI_INSTANCE_INTC |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No Kconfig is necessary
@@ -1237,7 +1240,8 @@ static const struct uart_driver_api uart_ns16550_driver_api = { | |||
static void irq_config_func##n(const struct device *dev) \ | |||
{ \ | |||
ARG_UNUSED(dev); \ | |||
IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \ | |||
NS16550_IRQ_CONNECT(DT_INST_INTC_PARENT(n), DT_INST_IRQN(n), \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this just be converted to use IRQ_INTC_CONNECT()
directly? It also looks like the first parameter is supposed to be an instance number, but here it's a const struct device *
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this approach, the IRQN doesn't carry information about the plic instance, we will need to pass in the parent interrupt controller of the uart
This actually looks somewhat reasonable to me, except for all of the DT changes. We don't need to adjust vendor .dts or .dtsi to fix the driver. I would leave that stuff alone. |
void z_riscv_plic_isr_install(unsigned int irq, unsigned int priority, | ||
void (*routine)(const void *), const void *param) | ||
{ | ||
z_riscv_plic_isr_intc_install(NULL, irq, priority, routine, param); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here, we have the ability to get dev
upfront, so might as well do that, and then it doesn't need to be done in z_riscv_plic_isr_intc_install()
bac14c6
to
70d98c7
Compare
ARG_UNUSED(flags); | ||
|
||
z_isr_install(irq, routine, parameter); | ||
|
||
#if defined(CONFIG_RISCV_HAS_PLIC) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pardon my ignorance but won't this break the shared interrupt support on PLIC-based RISCV SoCs? z_riscv_plic_isr_intc_install()
doesn't seem to be aware of the fact that the ISR may be set to z_shared_isr()
and will overwrite it. Is this behavior desired?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I'm aware of this issue, the isr installer in the shared interrupt part has to be updated as well for this approach to work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pardon my ignorance but won't this break the shared interrupt support on PLIC-based RISCV SoCs?
z_riscv_plic_isr_intc_install()
doesn't seem to be aware of the fact that the ISR may be set toz_shared_isr()
and will overwrite it. Is this behavior desired?
@LaurentiuM1234 - IIRC you recently updated the shared interrupt code. Were multi-level interrupts taken into account in the shared interrupt design?
If so, what would be the best way to support them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@LaurentiuM1234 - IIRC you recently updated the shared interrupt code. Were multi-level interrupts taken into account in the shared interrupt design?
Yes the shared interrupt code is aware of the multi-level organization of the interrupts via z_get_sw_isr_table_idx()
(for dynamic interrupts)
If so, what would be the best way to support them?
Mm, not sure how helpful I can be here since I'm not familiar with RISCV and its quirks. If the multiple PLIC instances are basically aggregators for different interrupt lines I would suggest taking a look at #62776. The idea is that you register a dispatcher for each of these interrupt lines which will, in turn, call of the higher level reigstered ISRs. z_isr_install()
is kept unchanged to keep the support for shared interrupts.
Use a config struct to store per-instance device config during init and connect the IRQ based on the devicetree instead of hardcoded value and instance. The `get_plic_dev_from_irq` is still a placeholder for now and always return the first instance. Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Extends the `riscv_plic` public header to provide an ISR installer. The ISR installer implementation in the `intc_plic` will install the ISR to the correct offset using infomation from the devicetree properties. The RISCV's `arch_irq_connect_dynamic` will use this ISR installer when `CONFIG_RISCV_HAS_PLIC` is enabled. Signed-off-by: Yong Cong Sin <ycsin@meta.com>
70d98c7
to
a1b9134
Compare
This PR add multi-instance support to the
intc_plic
driver. As all the IRQs are sharing the same ISR table, 2nd levels and onwards IRQs in one instance of a controller can collide with another in the ISR table.To avoid this, the ISR should have an offset as large as the sum of the number of IRQs in the previous instances in the devicetree, so they dont get installed to the same index.
The RISCV's
arch_irq_connect_dynamic
then get this offset from the controller to install the ISR accordingly.This PR aims to get a look and feel of the approach.
Why dont we just let interrupt controller to install the ISR?practiced in this PR, for RISCVintc_plic
only