| /* |
| * Copyright (c) 2020 Linaro Ltd. |
| * Copyright (c) 2020 ATL Electronics |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| /** @file |
| * @brief Cypress PSoC-6 MCU family devicetree helper macros |
| */ |
| |
| #ifndef _CYPRESS_PSOC6_DT_H_ |
| #define _CYPRESS_PSOC6_DT_H_ |
| |
| #include <devicetree.h> |
| |
| /* |
| * Devicetree macros related to interrupt |
| * |
| * The main "API" macro is CY_PSOC6_IRQ_CONFIG. It is an internal definition |
| * used to configure the PSoC-6 interrupts in a generic way. This is necessary |
| * because Cortex-M0+ can handle a limited number of interrupts and have |
| * multiplexers in front of any NVIC interrupt line. |
| * |
| * The CY_PSOC6_IRQ_CONFIG expands from CY_PSOC6_DT_INST_NVIC_INSTALL, the |
| * public API used by drivers. See below code fragment: |
| * |
| * static void <driver>_psoc6_isr(const struct device *dev) |
| * { |
| * ... |
| * } |
| * |
| * #define <DRIVER>_PSOC6_INIT(n) \ |
| * ... \ |
| * static void <driver>_psoc6_irq_config(const struct device *port) \ |
| * { \ |
| * CY_PSOC6_DT_INST_NVIC_INSTALL(n, \ |
| * <driver>_psoc6_isr); \ |
| * }; \ |
| * }; |
| * |
| * where: |
| * n - driver instance number |
| * isr - isr function to be called |
| * |
| * Cortex-M4 simple pass the parameter and constructs an usual NVIC |
| * configuration code. |
| * |
| * The Cortex-M0+ must get from interrupt parent the interrupt line and |
| * configure the interrupt channel to connect PSoC-6 peripheral interrupt to |
| * Cortex-M0+ NVIC. The multiplexer is configured by CY_PSOC6_DT_NVIC_MUX_MAP |
| * using the interrupt value from the interrupt parent. |
| * |
| * see cypress,psoc6-int-mux.yaml for devicetree documentation. |
| */ |
| #ifdef CONFIG_CPU_CORTEX_M0PLUS |
| /* Cortex-M0+ |
| * - install config only when exists an interrupt_parent property |
| * - get peripheral irq using PROP_BY_INDEX, to avoid translation from |
| * interrupt-parent node property. |
| * - configure interrupt channel using the channel number register value from |
| * interrupt-parent node. |
| */ |
| #define CY_PSOC6_DT_INST_NVIC_INSTALL(n, isr) \ |
| IF_ENABLED(DT_INST_NODE_HAS_PROP(n, interrupt_parent),\ |
| (CY_PSOC6_IRQ_CONFIG(n, isr))) |
| #define CY_PSOC6_NVIC_MUX_IRQN(n) DT_IRQN(DT_INST_PHANDLE_BY_IDX(n,\ |
| interrupt_parent, 0)) |
| /* |
| * DT_INST_PROP_BY_IDX should be used get interrupt and configure, instead |
| * DT_INST_IRQN. The DT_INST_IRQN return IRQ number with level translation, |
| * since it uses interrupt-parent, and the value at Cortex-M0 NVIC multiplexers |
| * will be wrong. |
| * |
| * See multi-level-interrupt-handling. |
| */ |
| #define CY_PSOC6_NVIC_MUX_MAP(n) Cy_SysInt_SetInterruptSource( \ |
| DT_IRQN(DT_INST_PHANDLE_BY_IDX(n,\ |
| interrupt_parent, 0)), \ |
| DT_INST_PROP_BY_IDX(n, interrupts, 0)) |
| #else |
| /* Cortex-M4 |
| * - bypass config |
| * - uses irq directly from peripheral devicetree definition |
| * - no map/translations |
| */ |
| #define CY_PSOC6_DT_INST_NVIC_INSTALL(n, isr) CY_PSOC6_IRQ_CONFIG(n, isr) |
| #define CY_PSOC6_NVIC_MUX_IRQN(n) DT_INST_IRQN(n) |
| #define CY_PSOC6_NVIC_MUX_MAP(n) |
| #endif |
| |
| #define CY_PSOC6_IRQ_CONFIG(n, isr) \ |
| do { \ |
| IRQ_CONNECT(CY_PSOC6_NVIC_MUX_IRQN(n), \ |
| DT_INST_IRQ(n, priority), \ |
| isr, DEVICE_DT_INST_GET(n), 0);\ |
| CY_PSOC6_NVIC_MUX_MAP(n); \ |
| irq_enable(CY_PSOC6_NVIC_MUX_IRQN(n)); \ |
| } while (0) |
| |
| #endif /* _CYPRESS_PSOC6_SOC_DT_H_ */ |