Skip to content

Commit 463374f

Browse files
mstasiaknordicnordicjm
authored andcommitted
[nrf fromlist] drivers: spi: nrfx_spi(m/s): enable cross domain pins for nRF54L15
SPI(M/S)20 and SPIM(M/S)21 instances enable usage of pins on different port, but require request for constant latency mode. Added handling of such scenario in the driver. Added testcase to cover it. Upstream PR #: 90197 Signed-off-by: Michał Stasiak <[email protected]>
1 parent cee404d commit 463374f

File tree

6 files changed

+288
-22
lines changed

6 files changed

+288
-22
lines changed

drivers/spi/spi_nrfx_spim.c

Lines changed: 93 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ LOG_MODULE_REGISTER(spi_nrfx_spim, CONFIG_SPI_LOG_LEVEL);
4343
#define SPI_BUFFER_IN_RAM 1
4444
#endif
4545

46+
/*
47+
* We use NODELABEL here because the nrfx API requires us to call
48+
* functions which are named according to SoC peripheral instance
49+
* being operated on. Since DT_INST() makes no guarantees about that,
50+
* it won't work.
51+
*/
52+
#define SPIM(idx) DT_NODELABEL(spi##idx)
53+
#define SPIM_PROP(idx, prop) DT_PROP(SPIM(idx), prop)
54+
#define SPIM_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(SPIM(idx), prop)
55+
4656
#if defined(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL)
4757
#define SPIM_REQUESTS_CLOCK(node) \
4858
DT_NODE_HAS_COMPAT(DT_CLOCKS_CTLR(node), nordic_nrf_hsfll_global)
@@ -59,6 +69,28 @@ BUILD_ASSERT(!IS_ENABLED(CONFIG_PM_DEVICE_SYSTEM_MANAGED));
5969
#define SPIM_REQUESTS_CLOCK(node) 0
6070
#endif
6171

72+
#define SPIM_PINS_CROSS_DOMAIN(unused, prefix, idx, _) \
73+
COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(SPIM(prefix##idx)), \
74+
(SPIM_PROP(idx, cross_domain_pins_supported)), \
75+
(0))
76+
77+
#if NRFX_FOREACH_PRESENT(SPIM, SPIM_PINS_CROSS_DOMAIN, (||), (0))
78+
#include <hal/nrf_gpio.h>
79+
/* Certain SPIM instances support usage of cross domain pins in form of dedicated pins on
80+
* a port different from the default one.
81+
*/
82+
#define SPIM_CROSS_DOMAIN_SUPPORTED 1
83+
#endif
84+
85+
#if SPIM_CROSS_DOMAIN_SUPPORTED && defined(CONFIG_NRF_SYS_EVENT)
86+
#include <nrf_sys_event.h>
87+
/* To use cross domain pins, constant latency mode needs to be applied, which is
88+
* handled via nrf_sys_event requests.
89+
*/
90+
#define SPIM_CROSS_DOMAIN_PINS_HANDLE 1
91+
#endif
92+
93+
6294
struct spi_nrfx_data {
6395
struct spi_context ctx;
6496
const struct device *dev;
@@ -98,6 +130,10 @@ struct spi_nrfx_config {
98130
const struct device *clk_dev;
99131
struct nrf_clock_spec clk_spec;
100132
#endif
133+
#if SPIM_CROSS_DOMAIN_SUPPORTED
134+
bool cross_domain;
135+
int8_t default_port;
136+
#endif
101137
};
102138

103139
static void event_handler(const nrfx_spim_evt_t *p_event, void *p_context);
@@ -147,6 +183,32 @@ static inline void release_clock(const struct device *dev)
147183
#endif
148184
}
149185

186+
#if SPIM_CROSS_DOMAIN_SUPPORTED
187+
static bool spim_has_cross_domain_connection(const struct spi_nrfx_config *config)
188+
{
189+
const struct pinctrl_dev_config *pcfg = config->pcfg;
190+
const struct pinctrl_state *state;
191+
int ret;
192+
193+
ret = pinctrl_lookup_state(pcfg, PINCTRL_STATE_DEFAULT, &state);
194+
if (ret < 0) {
195+
LOG_ERR("Unable to read pin state");
196+
return false;
197+
}
198+
199+
for (uint8_t i = 0U; i < state->pin_cnt; i++) {
200+
uint32_t pin = NRF_GET_PIN(state->pins[i]);
201+
202+
if ((pin != NRF_PIN_DISCONNECTED) &&
203+
(nrf_gpio_pin_port_number_extract(&pin) != config->default_port)) {
204+
return true;
205+
}
206+
}
207+
208+
return false;
209+
}
210+
#endif
211+
150212
static inline void finalize_spi_transaction(const struct device *dev, bool deactivate_cs)
151213
{
152214
struct spi_nrfx_data *dev_data = dev->data;
@@ -688,6 +750,19 @@ static int spim_resume(const struct device *dev)
688750
#ifdef CONFIG_SOC_NRF54H20_GPD
689751
nrf_gpd_retain_pins_set(dev_config->pcfg, false);
690752
#endif
753+
#if SPIM_CROSS_DOMAIN_SUPPORTED
754+
if (dev_config->cross_domain && spim_has_cross_domain_connection(dev_config)) {
755+
#if SPIM_CROSS_DOMAIN_PINS_HANDLE
756+
int err;
757+
758+
err = nrf_sys_event_request_global_constlat();
759+
(void)err;
760+
__ASSERT_NO_MSG(err >= 0);
761+
#else
762+
__ASSERT(false, "NRF_SYS_EVENT needs to be enabled to use cross domain pins.\n");
763+
#endif
764+
}
765+
#endif
691766

692767
return IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME) ? request_clock(dev) : 0;
693768
}
@@ -711,6 +786,19 @@ static void spim_suspend(const struct device *dev)
711786
#ifdef CONFIG_SOC_NRF54H20_GPD
712787
nrf_gpd_retain_pins_set(dev_config->pcfg, true);
713788
#endif
789+
#if SPIM_CROSS_DOMAIN_SUPPORTED
790+
if (dev_config->cross_domain && spim_has_cross_domain_connection(dev_config)) {
791+
#if SPIM_CROSS_DOMAIN_PINS_HANDLE
792+
int err;
793+
794+
err = nrf_sys_event_request_global_constlat();
795+
(void)err;
796+
__ASSERT_NO_MSG(err >= 0);
797+
#else
798+
__ASSERT(false, "NRF_SYS_EVENT needs to be enabled to use cross domain pins.\n");
799+
#endif
800+
}
801+
#endif
714802

715803
(void)pinctrl_apply_state(dev_config->pcfg, PINCTRL_STATE_SLEEP);
716804
}
@@ -790,15 +878,6 @@ static int spi_nrfx_deinit(const struct device *dev)
790878
return 0;
791879
}
792880

793-
/*
794-
* We use NODELABEL here because the nrfx API requires us to call
795-
* functions which are named according to SoC peripheral instance
796-
* being operated on. Since DT_INST() makes no guarantees about that,
797-
* it won't work.
798-
*/
799-
#define SPIM(idx) DT_NODELABEL(spi##idx)
800-
#define SPIM_PROP(idx, prop) DT_PROP(SPIM(idx), prop)
801-
#define SPIM_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(SPIM(idx), prop)
802881
#define SPIM_MEM_REGION(idx) DT_PHANDLE(SPIM(idx), memory_regions)
803882

804883
#define SPI_NRFX_SPIM_EXTENDED_CONFIG(idx) \
@@ -890,6 +969,11 @@ static int spi_nrfx_deinit(const struct device *dev)
890969
.clk_spec = { \
891970
.frequency = NRF_CLOCK_CONTROL_FREQUENCY_MAX, \
892971
},)) \
972+
IF_ENABLED(SPIM_PINS_CROSS_DOMAIN(_, /*empty*/, idx, _), \
973+
(.cross_domain = true, \
974+
.default_port = \
975+
DT_PROP_OR(DT_PHANDLE(SPIM(idx), \
976+
default_gpio_port), port, -1),)) \
893977
}; \
894978
BUILD_ASSERT(!SPIM_HAS_PROP(idx, wake_gpios) || \
895979
!(DT_GPIO_FLAGS(SPIM(idx), wake_gpios) & GPIO_ACTIVE_LOW),\

drivers/spi/spi_nrfx_spis.c

Lines changed: 93 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,38 @@ LOG_MODULE_REGISTER(spi_nrfx_spis, CONFIG_SPI_LOG_LEVEL);
3636
BUILD_ASSERT(!IS_ENABLED(CONFIG_PM_DEVICE_SYSTEM_MANAGED));
3737
#endif
3838

39+
/*
40+
* Current factors requiring use of DT_NODELABEL:
41+
*
42+
* - HAL design (requirement of drv_inst_idx in nrfx_spis_t)
43+
* - Name-based HAL IRQ handlers, e.g. nrfx_spis_0_irq_handler
44+
*/
45+
#define SPIS_NODE(idx) COND_CODE_1(SPIS_IS_FAST(idx), (spis##idx), (spi##idx))
46+
#define SPIS(idx) DT_NODELABEL(SPIS_NODE(idx))
47+
#define SPIS_PROP(idx, prop) DT_PROP(SPIS(idx), prop)
48+
#define SPIS_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(SPIS(idx), prop)
49+
50+
#define SPIS_PINS_CROSS_DOMAIN(unused, prefix, idx, _) \
51+
COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(SPIS(prefix##idx)), \
52+
(SPIS_PROP(idx, cross_domain_pins_supported)), \
53+
(0))
54+
55+
#if NRFX_FOREACH_PRESENT(SPIS, SPIS_PINS_CROSS_DOMAIN, (||), (0))
56+
#include <hal/nrf_gpio.h>
57+
/* Certain SPIM instances support usage of cross domain pins in form of dedicated pins on
58+
* a port different from the default one.
59+
*/
60+
#define SPIS_CROSS_DOMAIN_SUPPORTED 1
61+
#endif
62+
63+
#if SPIS_CROSS_DOMAIN_SUPPORTED && defined(CONFIG_NRF_SYS_EVENT)
64+
#include <nrf_sys_event.h>
65+
/* To use cross domain pins, constant latency mode needs to be applied, which is
66+
* handled via nrf_sys_event requests.
67+
*/
68+
#define SPIS_CROSS_DOMAIN_PINS_HANDLE 1
69+
#endif
70+
3971
struct spi_nrfx_data {
4072
struct spi_context ctx;
4173
const struct device *dev;
@@ -58,8 +90,38 @@ struct spi_nrfx_config {
5890
const struct pinctrl_dev_config *pcfg;
5991
struct gpio_dt_spec wake_gpio;
6092
void *mem_reg;
93+
#if SPIS_CROSS_DOMAIN_SUPPORTED
94+
bool cross_domain;
95+
int8_t default_port;
96+
#endif
6197
};
6298

99+
#if SPIS_CROSS_DOMAIN_SUPPORTED
100+
static bool spis_has_cross_domain_connection(const struct spi_nrfx_config *config)
101+
{
102+
const struct pinctrl_dev_config *pcfg = config->pcfg;
103+
const struct pinctrl_state *state;
104+
int ret;
105+
106+
ret = pinctrl_lookup_state(pcfg, PINCTRL_STATE_DEFAULT, &state);
107+
if (ret < 0) {
108+
LOG_ERR("Unable to read pin state");
109+
return false;
110+
}
111+
112+
for (uint8_t i = 0U; i < state->pin_cnt; i++) {
113+
uint32_t pin = NRF_GET_PIN(state->pins[i]);
114+
115+
if ((pin != NRF_PIN_DISCONNECTED) &&
116+
(nrf_gpio_pin_port_number_extract(&pin) != config->default_port)) {
117+
return true;
118+
}
119+
}
120+
121+
return false;
122+
}
123+
#endif
124+
63125
static inline nrf_spis_mode_t get_nrf_spis_mode(uint16_t operation)
64126
{
65127
if (SPI_MODE_GET(operation) & SPI_MODE_CPOL) {
@@ -384,6 +446,19 @@ static void spi_nrfx_suspend(const struct device *dev)
384446
nrf_gpd_retain_pins_set(dev_config->pcfg, true);
385447
}
386448
#endif
449+
#if SPIS_CROSS_DOMAIN_SUPPORTED
450+
if (dev_config->cross_domain && spis_has_cross_domain_connection(dev_config)) {
451+
#if SPIS_CROSS_DOMAIN_PINS_HANDLE
452+
int err;
453+
454+
err = nrf_sys_event_request_global_constlat();
455+
(void)err;
456+
__ASSERT_NO_MSG(err >= 0);
457+
#else
458+
__ASSERT(false, "NRF_SYS_EVENT needs to be enabled to use cross domain pins.\n");
459+
#endif
460+
}
461+
#endif
387462

388463
(void)pinctrl_apply_state(dev_config->pcfg, PINCTRL_STATE_SLEEP);
389464
}
@@ -399,6 +474,19 @@ static void spi_nrfx_resume(const struct device *dev)
399474
nrf_gpd_retain_pins_set(dev_config->pcfg, false);
400475
}
401476
#endif
477+
#if SPIS_CROSS_DOMAIN_SUPPORTED
478+
if (dev_config->cross_domain && spis_has_cross_domain_connection(dev_config)) {
479+
#if SPIS_CROSS_DOMAIN_PINS_HANDLE
480+
int err;
481+
482+
err = nrf_sys_event_request_global_constlat();
483+
(void)err;
484+
__ASSERT_NO_MSG(err >= 0);
485+
#else
486+
__ASSERT(false, "NRF_SYS_EVENT needs to be enabled to use cross domain pins.\n");
487+
#endif
488+
}
489+
#endif
402490

403491
if (dev_config->wake_gpio.port == NULL) {
404492
nrf_spis_enable(dev_config->spis.p_reg);
@@ -482,19 +570,6 @@ static int spi_nrfx_init(const struct device *dev)
482570
return pm_device_driver_init(dev, spi_nrfx_pm_action);
483571
}
484572

485-
/*
486-
* Current factors requiring use of DT_NODELABEL:
487-
*
488-
* - HAL design (requirement of drv_inst_idx in nrfx_spis_t)
489-
* - Name-based HAL IRQ handlers, e.g. nrfx_spis_0_irq_handler
490-
*/
491-
492-
#define SPIS_NODE(idx) COND_CODE_1(SPIS_IS_FAST(idx), (spis##idx), (spi##idx))
493-
494-
#define SPIS(idx) DT_NODELABEL(SPIS_NODE(idx))
495-
496-
#define SPIS_PROP(idx, prop) DT_PROP(SPIS(idx), prop)
497-
498573
#define SPI_NRFX_SPIS_DEFINE(idx) \
499574
static void irq_connect##idx(void) \
500575
{ \
@@ -533,6 +608,11 @@ static int spi_nrfx_init(const struct device *dev)
533608
NRFX_MHZ_TO_HZ(16UL),)) \
534609
.wake_gpio = GPIO_DT_SPEC_GET_OR(SPIS(idx), wake_gpios, {0}), \
535610
.mem_reg = DMM_DEV_TO_REG(SPIS(idx)), \
611+
IF_ENABLED(SPIS_PINS_CROSS_DOMAIN(_, /*empty*/, idx, _), \
612+
(.cross_domain = true, \
613+
.default_port = \
614+
DT_PROP_OR(DT_PHANDLE(SPIS(idx), \
615+
default_gpio_port), port, -1),)) \
536616
}; \
537617
BUILD_ASSERT(!DT_NODE_HAS_PROP(SPIS(idx), wake_gpios) || \
538618
!(DT_GPIO_FLAGS(SPIS(idx), wake_gpios) & GPIO_ACTIVE_LOW),\

dts/bindings/spi/nordic,nrf-spi-common.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,13 @@ properties:
6161
and SPI master again keeps the line in the low state
6262
Please note that the line must be configured and properly handled on
6363
both sides for the mechanism to work correctly.
64+
65+
default-gpio-port:
66+
type: phandle
67+
description: |
68+
SPI default GPIO port.
69+
70+
cross-domain-pins-supported:
71+
type: boolean
72+
description: |
73+
SPI allows usage of cross domain pins with constant latency mode required.

dts/vendor/nordic/nrf54l_05_10_15.dtsi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,8 @@
313313
rx-delay-supported;
314314
rx-delay = <1>;
315315
status = "disabled";
316+
default-gpio-port = <&gpio1>;
317+
cross-domain-pins-supported;
316318
};
317319

318320
uart20: uart@c6000 {
@@ -354,6 +356,8 @@
354356
rx-delay-supported;
355357
rx-delay = <1>;
356358
status = "disabled";
359+
default-gpio-port = <&gpio1>;
360+
cross-domain-pins-supported;
357361
};
358362

359363
uart21: uart@c7000 {

0 commit comments

Comments
 (0)