When not using dynamic interrupt mapping, various interrupt tables are
configured to be stored in read-only memory in the linker script.. Mark
them const so that the linker doesn't complain.
This affects _sw_isr_table, _irq_vector_table, and z_shared_sw_isr_table in
arch/common along with _VectorTable in arch/arc.
Signed-off-by: Keith Packard <keithp@keithp.com>
Instead of doing an `irq_lock()`, use per-instance spinlock instead.
Refactored out an unlocked version of `local_irq_is_enabled`
from `riscv_plic_irq_is_enabled()` to achieve that.
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
The `arch_proc_id()` returns the hartid of a CPU, which may not start
from zero. The way that it's used as an index to access `save_irq[]`
array is wrong, use `arch_curr_cpu()->id` instead.
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Signed-off-by: Yong Cong Sin <yongcong.sin@gmail.com>
Convert the compilation of the trigger type feature to depend
on Kconfig, following the same pattern of software-triggered
interrupt.
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Signed-off-by: Yong Cong Sin <yongcong.sin@gmail.com>
Implement `riscv_plic_irq_set_pending()` to trigger a
software-generated interrupt.
The "4. Interrupt Pending Bits" of the riscv-plic specs
described the reading of the pending bits, but not the writing
Since not all PLIC implementations support software-generated
interrupt, the function is compiled only when
`CONFIG_PLIC_SUPPORTS_SOFT_INTERRUPT` is enabled on PLIC that
supports it, such as the Andes' NCEPLIC100.
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Signed-off-by: Yong Cong Sin <yongcong.sin@gmail.com>
The functions to obtain the address are hardcoded to return
the address of the first core when `CONFIG_SMP != y`, this
causes an issue with enabling an IRQ when there are more than
one core in the system (`CONFIG_MP_MAX_NUM_CPUS > 1`), as the
driver would first enable the IRQ on the first core, and when
it tries to obtain the address for the following cores and
disable the IRQ on them, the functions continue to return the
address of the first core, causing the IRQ to be disabled
on the first core.
Fix this by determine if `CONFIG_MP_MAX_NUM_CPUS > 1` instead
of `CONFIG_SMP=y` when returning the address.
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Signed-off-by: Yong Cong Sin <yongcong.sin@gmail.com>
- Implement irq-set-affinity in RISCV PLIC.
- Added new affinity shell command to get/set the irq(s)
affinity in runtime, when `0` is sent as the `local_irq`, it
means set/get all IRQs affinity.
- Some minor optimizations
Updated the build_all test to build this new configuration.
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Signed-off-by: Yong Cong Sin <yongcong.sin@gmail.com>
Allow IRQs to work on every hart regardless of the mapping
of the contexts.
Add a test to validate the hart-context mapping.
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Signed-off-by: Yong Cong Sin <yongcong.sin@gmail.com>
Move the lock out from the `plic_irq_enable_set_state()` function
to cover the entire configuration process, so the whole of
enable/disable is atomic.
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Signed-off-by: Yong Cong Sin <yongcong.sin@gmail.com>
Add missing braces to comply with MISRA C:2012 Rule 15.6 and
also following Zephyr's style guideline.
Signed-off-by: Pisit Sawangvonganan <pisit@ndrsolution.com>
Print the ISR & its ARG along with the IRQ and Hits in
`plic stats get <intc>` command, i.e.
```CONFIG_SYMTAB=n
uart:~$ plic stats get interrupt-controller@c000000
IRQ Hits ISR(ARG)
10 541 0x800054ee(0x80008170)
```
```CONFIG_SYMTAB=y
uart:~$ plic stats get interrupt-controller@c000000
IRQ Hits ISR(ARG)
10 114 uart_ns16550_isr(0x80008230)
```
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Signed-off-by: Yong Cong Sin <yongcong.sin@gmail.com>
Save the reference of the start index of the `_sw_isr_table`
to the config struct, so that the `local_irq` can be used as
offset directly.
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Previously the multi-level irq lookup table is generated by
looping through the devicetree nodes using macros & Kconfig,
which is hard to read and flimsy.
This PR shifts the heavy lifting to devicetree & DT macros such
that an interrupt controller driver, which has its info in the
devicetree, can register itself directly with the multi-level
interrupt architecture, which is more straightforward.
The previous auto-generated look up table with macros is now
moved in a file of its own. A new compatibility Kconfig:
`CONFIG_LEGACY_MULTI_LEVEL_TABLE_GENERATION` is added and
enabled by default to compile the legacy look up table for
interrupt controller drivers that aren't updated to support the
new architecture yet.
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Interrupt trigger type register each bit indicate the configured interrupt
type. bit value is 0 indicate level trigger interrupt, 1 indicate edge
trigger interrupt.
The level trigger defined to ~BIT(0) equal 0xfffffffe not equal 0.
Signed-off-by: Weiwei Guo <guoweiwei@syriusrobotics.com>
Introduce a new arch level Kconfig option to signal the implementation
of the RISCV Privileged ISA spec. This replaces
SOC_FAMILY_RISCV_PRIVILEGED, because this is not a SoC specific
property, nor a SoC family.
Note that the SoC family naming scheme will be fixed in upcoming
commits.
Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
Store the compile-time computed length of the `irq_count` into
a variable so that we have less to do in runtime.
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Change the index variable type to `int` from `size_t` to compile
across 32bit and 64bit platforms without generating warnings.
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
The plic has a very simple mechanism to claim an interrupt as well as to
complete and clear it. The same register is read from/ written to to
achieve this.
Get the ID of the HART that serviced the interrupt and write to the
claim complete register in the correct context
Signed-off-by: Conor Paxton <conor.paxton@microchip.com>
The plic uses contexts to seperate irq enables, threshold priority and
claim complete registers from each core for a given platform. As well as
this, each privilege level has its own context.
for multi-core platform's, we need to be able to enable/ disable a
global interrupt for all the cores that are associated with Zephyr.
To do this, we need to make some assumptions:
1. The privilege contexts are contiguous
2. M mode context is first, followed by S mode.
We know how many cpus are used in an application and each cpu's hartid,
thanks to some very handy inline functions. So we iterate through each
cpu and use the hartid of a cpu in the calculation of the context.
While we are at it, In an effort to make the driver more readable,
allign with the macro naming convention outlined in Linux's PLIC driver
Signed-off-by: Conor Paxton <conor.paxton@microchip.com>
Define the edge-trigger register base address based on whether
the PLIC node in the devicetree has an additional compatible
that supports edge-triggered interrupt.
Limited the implementation to Andes NCEPLIC100 only, updated
the devicetree binding of `andes_v5_ae350` accordingly.
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
There's a ternary operator that depends on configuration-defined macro:
`CONFIG_DYNAMIC_INTERRUPTS` is not enabled by default
for any of the platforms that use PLIC,
it is possbile to set it to `=y` though.
This triggered the Coverity check to report it as dead code.
Fixes#65576.
Signed-off-by: Wojciech Sipak <wsipak@antmicro.com>
The `riscv_plic_irq_enable` & `riscv_plic_irq_disable` are very
similar, refactor them out into `plic_irq_enable_set_state`.
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Introduced `CONFIG_PLIC_SHELL` to enable the build of shell
debugging command to get the hit count of each interrupt
controller's IRQ line. This is especially useful when working
with dynamically installed ISRs, which will be the case for
`plic_sw`.
Example usage:
```
uart:~$ plic stats get interrupt-controller@c000000
IRQ Hits
==================
10 177
uart:~$ plic stats get interrupt-controller@c000000
IRQ Hits
==================
10 236
uart:~$ plic stats clear interrupt-controller@c000000
Cleared stats of interrupt-controller@c000000.
uart:~$ plic stats get interrupt-controller@c000000
IRQ Hits
==================
10 90
```
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Signed-off-by: Maxim Adelman <imax@meta.com>
if-conditionals should have brackets according to Zephyr's
coding standard, and explicitly compares `edge_irq` against 0.
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Previously, the PLIC's registers were accessed through uint32_t *,
so all calculated offsets were effectively multiplied by
sizeof(uint32_t). Do the same manuallly now that we have
mem_addr_t/sys_read32.
Signed-off-by: Piotr Wojnarowski <pwojnarowski@antmicro.com>
`get_claim_complete_offset` and `get_threshold_priority_offset` actually
return addresses directly. Rename them to `_addr` for consistency within
the driver. Also change their return type to `mem_addr_t`.
Signed-off-by: Piotr Wojnarowski <pwojnarowski@antmicro.com>
Use arch-specific sys IO APIs to access the memory-mapped
registers to ensure safe memory operations
fixes#62956
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Added some defines and helper functions to help with the
arithmetics so that the bit shifts and stuff do not look like
magic number.
Converted manual bit shift/set/unset to use macros provided by
Zephyr.
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Most of the public APIs in `riscv_plic.h`
(except `riscv_plic_get_irq` & `riscv_plic_get_dev`) expect the
`irq` argument to be in Zephyr-encoded format, instead of the
previously `irq_from_level_2`-stripped version. The first level
IRQ is needed by `intc_plic` to differentiate between the
parent interrupt controllers, so that correct ISR offset can be
obtained using the LUT in `sw_isr_common`.
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
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 number.
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>
Define all the register offset directly in the driver according
to the RISCV PLIC specification as they are not configurable,
see: https://github.com/riscv/riscv-plic-spec.
Updated devicetrees that has PLIC accordingly.
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Removing the edge-trigger Kconfig as it is supported by default
in the RISCV PLIC specifications.
Define the edge-trigger register offset in the driver instead
of retrieving the value from devicetree as it is not something
configurable. The value 0x1080 is defined in Andes & Telink
datasheets.
Updated build_all testcase.
Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Convert SYS_INIT to DEVICE_DT_INST_DEFINE, this allows the build system
to track the device dependencies and ensure that the interrupt
controller is initialized before other devices using it.
Signed-off-by: Fabio Baltieri <fabiobaltieri@google.com>
Usage of 64-bit address constants from devicetree without
an UINT64_C wrapping macro results in the following warning
and the cut-off of the address value:
"warning: integer constant is so large that it is unsigned"
This change fixes such issue for PLIC, MTIMER and UART in case
they are used with some 64-bit RISC-V platforms
Signed-off-by: Alexander Razinkov <alexander.razinkov@syntacore.com>
The init infrastructure, found in `init.h`, is currently used by:
- `SYS_INIT`: to call functions before `main`
- `DEVICE_*`: to initialize devices
They are all sorted according to an initialization level + a priority.
`SYS_INIT` calls are really orthogonal to devices, however, the required
function signature requires a `const struct device *dev` as a first
argument. The only reason for that is because the same init machinery is
used by devices, so we have something like:
```c
struct init_entry {
int (*init)(const struct device *dev);
/* only set by DEVICE_*, otherwise NULL */
const struct device *dev;
}
```
As a result, we end up with such weird/ugly pattern:
```c
static int my_init(const struct device *dev)
{
/* always NULL! add ARG_UNUSED to avoid compiler warning */
ARG_UNUSED(dev);
...
}
```
This is really a result of poor internals isolation. This patch proposes
a to make init entries more flexible so that they can accept sytem
initialization calls like this:
```c
static int my_init(void)
{
...
}
```
This is achieved using a union:
```c
union init_function {
/* for SYS_INIT, used when init_entry.dev == NULL */
int (*sys)(void);
/* for DEVICE*, used when init_entry.dev != NULL */
int (*dev)(const struct device *dev);
};
struct init_entry {
/* stores init function (either for SYS_INIT or DEVICE*)
union init_function init_fn;
/* stores device pointer for DEVICE*, NULL for SYS_INIT. Allows
* to know which union entry to call.
*/
const struct device *dev;
}
```
This solution **does not increase ROM usage**, and allows to offer clean
public APIs for both SYS_INIT and DEVICE*. Note that however, init
machinery keeps a coupling with devices.
**NOTE**: This is a breaking change! All `SYS_INIT` functions will need
to be converted to the new signature. See the script offered in the
following commit.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
init: convert SYS_INIT functions to the new signature
Conversion scripted using scripts/utils/migrate_sys_init.py.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
manifest: update projects for SYS_INIT changes
Update modules with updated SYS_INIT calls:
- hal_ti
- lvgl
- sof
- TraceRecorderSource
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
tests: devicetree: devices: adjust test
Adjust test according to the recently introduced SYS_INIT
infrastructure.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
tests: kernel: threads: adjust SYS_INIT call
Adjust to the new signature: int (*init_fn)(void);
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
Change automated searching for files using "IRQ_CONNECT()" API not
including <zephyr/irq.h>.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
In order to bring consistency in-tree, migrate all drivers to the new
prefix <zephyr/...>. Note that the conversion has been scripted, refer
to #45388 for more details.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
Refactors interrupt controller drivers to use the shared driver class
initialization priority configuration, CONFIG_INTC_INIT_PRIORITY, to
allow configuring interrupt controller drivers separately from other
devices. This is similar to other driver classes.
The default is set to CONFIG_KERNEL_INIT_PRIORITY_DEFAULT to preserve
the existing default initialization priority for most drivers.
Signed-off-by: Maureen Helm <maureen.helm@intel.com>
For functions returning nothing, there is no need to document
with @return, as Doxgen complains about "documented empty
return type of ...".
Signed-off-by: Daniel Leung <daniel.leung@intel.com>
Now that device_api attribute is unmodified at runtime, as well as all
the other attributes, it is possible to switch all device driver
instance to be constant.
A coccinelle rule is used for this:
@r_const_dev_1
disable optional_qualifier
@
@@
-struct device *
+const struct device *
@r_const_dev_2
disable optional_qualifier
@
@@
-struct device * const
+const struct device *
Fixes#27399
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>