@@ -43,6 +43,16 @@ LOG_MODULE_REGISTER(spi_nrfx_spim, CONFIG_SPI_LOG_LEVEL);
43
43
#define SPI_BUFFER_IN_RAM 1
44
44
#endif
45
45
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
+
46
56
#if defined(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL )
47
57
#define SPIM_REQUESTS_CLOCK (node ) \
48
58
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));
59
69
#define SPIM_REQUESTS_CLOCK (node ) 0
60
70
#endif
61
71
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
+
62
94
struct spi_nrfx_data {
63
95
struct spi_context ctx ;
64
96
const struct device * dev ;
@@ -98,6 +130,10 @@ struct spi_nrfx_config {
98
130
const struct device * clk_dev ;
99
131
struct nrf_clock_spec clk_spec ;
100
132
#endif
133
+ #if SPIM_CROSS_DOMAIN_SUPPORTED
134
+ bool cross_domain ;
135
+ int8_t default_port ;
136
+ #endif
101
137
};
102
138
103
139
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)
147
183
#endif
148
184
}
149
185
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
+
150
212
static inline void finalize_spi_transaction (const struct device * dev , bool deactivate_cs )
151
213
{
152
214
struct spi_nrfx_data * dev_data = dev -> data ;
@@ -688,6 +750,19 @@ static int spim_resume(const struct device *dev)
688
750
#ifdef CONFIG_SOC_NRF54H20_GPD
689
751
nrf_gpd_retain_pins_set (dev_config -> pcfg , false);
690
752
#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
691
766
692
767
return IS_ENABLED (CONFIG_PM_DEVICE_RUNTIME ) ? request_clock (dev ) : 0 ;
693
768
}
@@ -711,6 +786,19 @@ static void spim_suspend(const struct device *dev)
711
786
#ifdef CONFIG_SOC_NRF54H20_GPD
712
787
nrf_gpd_retain_pins_set (dev_config -> pcfg , true);
713
788
#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
714
802
715
803
(void )pinctrl_apply_state (dev_config -> pcfg , PINCTRL_STATE_SLEEP );
716
804
}
@@ -790,15 +878,6 @@ static int spi_nrfx_deinit(const struct device *dev)
790
878
return 0 ;
791
879
}
792
880
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)
802
881
#define SPIM_MEM_REGION (idx ) DT_PHANDLE(SPIM(idx), memory_regions)
803
882
804
883
#define SPI_NRFX_SPIM_EXTENDED_CONFIG (idx ) \
@@ -890,6 +969,11 @@ static int spi_nrfx_deinit(const struct device *dev)
890
969
.clk_spec = { \
891
970
.frequency = NRF_CLOCK_CONTROL_FREQUENCY_MAX, \
892
971
},)) \
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),)) \
893
977
}; \
894
978
BUILD_ASSERT(!SPIM_HAS_PROP(idx, wake_gpios) || \
895
979
!(DT_GPIO_FLAGS(SPIM(idx), wake_gpios) & GPIO_ACTIVE_LOW),\
0 commit comments