zephyr/soc/arm/cypress/common/cypress_psoc6_dt.h

102 lines
3.2 KiB
C

/*
* 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_ */