9
9
#include <zephyr/cache.h>
10
10
#include <zephyr/pm/device.h>
11
11
#include <zephyr/pm/device_runtime.h>
12
+ #include <zephyr/drivers/clock_control/nrf_clock_control.h>
12
13
#include <zephyr/drivers/pinctrl.h>
13
14
#include <zephyr/mem_mgmt/mem_attr.h>
14
15
#include <soc.h>
@@ -42,6 +43,16 @@ LOG_MODULE_REGISTER(spi_nrfx_spim, CONFIG_SPI_LOG_LEVEL);
42
43
#define SPI_BUFFER_IN_RAM 1
43
44
#endif
44
45
46
+ #if defined(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL ) && \
47
+ (defined(CONFIG_HAS_HW_NRF_SPIM120 ) || \
48
+ defined(CONFIG_HAS_HW_NRF_SPIM121 ))
49
+ #define SPIM_REQUESTS_CLOCK (idx ) UTIL_OR(IS_EQ(idx, 120), \
50
+ IS_EQ(idx, 121))
51
+ #define USE_CLOCK_REQUESTS 1
52
+ #else
53
+ #define SPIM_REQUESTS_CLOCK (idx ) 0
54
+ #endif
55
+
45
56
struct spi_nrfx_data {
46
57
struct spi_context ctx ;
47
58
const struct device * dev ;
@@ -57,6 +68,9 @@ struct spi_nrfx_data {
57
68
uint8_t ppi_ch ;
58
69
uint8_t gpiote_ch ;
59
70
#endif
71
+ #ifdef USE_CLOCK_REQUESTS
72
+ bool clock_requested ;
73
+ #endif
60
74
};
61
75
62
76
struct spi_nrfx_config {
@@ -74,10 +88,59 @@ struct spi_nrfx_config {
74
88
#ifdef CONFIG_DCACHE
75
89
uint32_t mem_attr ;
76
90
#endif
91
+ #ifdef USE_CLOCK_REQUESTS
92
+ const struct device * clk_dev ;
93
+ struct nrf_clock_spec clk_spec ;
94
+ #endif
77
95
};
78
96
79
97
static void event_handler (const nrfx_spim_evt_t * p_event , void * p_context );
80
98
99
+ static inline int request_clock (const struct device * dev )
100
+ {
101
+ #ifdef USE_CLOCK_REQUESTS
102
+ struct spi_nrfx_data * dev_data = dev -> data ;
103
+ const struct spi_nrfx_config * dev_config = dev -> config ;
104
+ int error ;
105
+
106
+ if (!dev_config -> clk_dev ) {
107
+ return 0 ;
108
+ }
109
+
110
+ error = nrf_clock_control_request_sync (
111
+ dev_config -> clk_dev , & dev_config -> clk_spec ,
112
+ K_MSEC (CONFIG_SPI_COMPLETION_TIMEOUT_TOLERANCE ));
113
+ if (error < 0 ) {
114
+ LOG_ERR ("Failed to request clock: %d" , error );
115
+ return error ;
116
+ }
117
+
118
+ dev_data -> clock_requested = true;
119
+ #else
120
+ ARG_UNUSED (dev );
121
+ #endif
122
+
123
+ return 0 ;
124
+ }
125
+
126
+ static inline void release_clock (const struct device * dev )
127
+ {
128
+ #ifdef USE_CLOCK_REQUESTS
129
+ struct spi_nrfx_data * dev_data = dev -> data ;
130
+ const struct spi_nrfx_config * dev_config = dev -> config ;
131
+
132
+ if (!dev_data -> clock_requested ) {
133
+ return ;
134
+ }
135
+
136
+ dev_data -> clock_requested = false;
137
+
138
+ nrf_clock_control_release (dev_config -> clk_dev , & dev_config -> clk_spec );
139
+ #else
140
+ ARG_UNUSED (dev );
141
+ #endif
142
+ }
143
+
81
144
static inline void finalize_spi_transaction (const struct device * dev , bool deactivate_cs )
82
145
{
83
146
struct spi_nrfx_data * dev_data = dev -> data ;
@@ -92,6 +155,10 @@ static inline void finalize_spi_transaction(const struct device *dev, bool deact
92
155
nrfy_spim_disable (reg );
93
156
}
94
157
158
+ if (!IS_ENABLED (CONFIG_PM_DEVICE_RUNTIME )) {
159
+ release_clock (dev );
160
+ }
161
+
95
162
pm_device_runtime_put_async (dev , K_NO_WAIT );
96
163
}
97
164
@@ -467,6 +534,11 @@ static int transceive(const struct device *dev,
467
534
spi_context_lock (& dev_data -> ctx , asynchronous , cb , userdata , spi_cfg );
468
535
469
536
error = configure (dev , spi_cfg );
537
+
538
+ if (error == 0 && !IS_ENABLED (CONFIG_PM_DEVICE_RUNTIME )) {
539
+ error = request_clock (dev );
540
+ }
541
+
470
542
if (error == 0 ) {
471
543
dev_data -> busy = true;
472
544
@@ -518,6 +590,8 @@ static int transceive(const struct device *dev,
518
590
} else if (error ) {
519
591
finalize_spi_transaction (dev , true);
520
592
}
593
+ } else {
594
+ pm_device_runtime_put (dev );
521
595
}
522
596
523
597
spi_context_release (& dev_data -> ctx , error );
@@ -575,7 +649,7 @@ static DEVICE_API(spi, spi_nrfx_driver_api) = {
575
649
.release = spi_nrfx_release ,
576
650
};
577
651
578
- static void spim_resume (const struct device * dev )
652
+ static int spim_resume (const struct device * dev )
579
653
{
580
654
const struct spi_nrfx_config * dev_config = dev -> config ;
581
655
@@ -587,6 +661,8 @@ static void spim_resume(const struct device *dev)
587
661
#ifdef CONFIG_SOC_NRF54H20_GPD
588
662
nrf_gpd_retain_pins_set (dev_config -> pcfg , false);
589
663
#endif
664
+
665
+ return IS_ENABLED (CONFIG_PM_DEVICE_RUNTIME ) ? request_clock (dev ) : 0 ;
590
666
}
591
667
592
668
static void spim_suspend (const struct device * dev )
@@ -599,6 +675,10 @@ static void spim_suspend(const struct device *dev)
599
675
dev_data -> initialized = false;
600
676
}
601
677
678
+ if (IS_ENABLED (CONFIG_PM_DEVICE_RUNTIME )) {
679
+ release_clock (dev );
680
+ }
681
+
602
682
#ifdef CONFIG_SOC_NRF54H20_GPD
603
683
nrf_gpd_retain_pins_set (dev_config -> pcfg , true);
604
684
#endif
@@ -609,7 +689,7 @@ static void spim_suspend(const struct device *dev)
609
689
static int spim_nrfx_pm_action (const struct device * dev , enum pm_device_action action )
610
690
{
611
691
if (action == PM_DEVICE_ACTION_RESUME ) {
612
- spim_resume (dev );
692
+ return spim_resume (dev );
613
693
} else if (IS_ENABLED (CONFIG_PM_DEVICE ) && (action == PM_DEVICE_ACTION_SUSPEND )) {
614
694
spim_suspend (dev );
615
695
} else {
@@ -685,6 +765,21 @@ static int spi_nrfx_init(const struct device *dev)
685
765
(0))), \
686
766
(0))
687
767
768
+ /* Fast instances depend on the global HSFLL clock controller (as they need
769
+ * to request the highest frequency from it to operate correctly), so they
770
+ * must be initialized after that controller driver, hence the default SPI
771
+ * initialization priority may be too early for them.
772
+ */
773
+ #if defined(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY ) && \
774
+ CONFIG_SPI_INIT_PRIORITY < CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY
775
+ #define SPIM_INIT_PRIORITY (idx ) \
776
+ COND_CODE_1(SPIM_REQUESTS_CLOCK(idx), \
777
+ (UTIL_INC(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY)), \
778
+ (CONFIG_SPI_INIT_PRIORITY))
779
+ #else
780
+ #define SPIM_INIT_PRIORITY (idx ) CONFIG_SPI_INIT_PRIORITY
781
+ #endif
782
+
688
783
#define SPI_NRFX_SPIM_DEFINE (idx ) \
689
784
NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(SPIM(idx)); \
690
785
static void irq_connect##idx(void) \
@@ -735,6 +830,13 @@ static int spi_nrfx_init(const struct device *dev)
735
830
.wake_gpiote = WAKE_GPIOTE_INSTANCE(SPIM(idx)), \
736
831
IF_ENABLED(CONFIG_DCACHE, \
737
832
(.mem_attr = SPIM_GET_MEM_ATTR(idx),)) \
833
+ IF_ENABLED(USE_CLOCK_REQUESTS, \
834
+ (.clk_dev = SPIM_REQUESTS_CLOCK(idx) \
835
+ ? DEVICE_DT_GET(DT_CLOCKS_CTLR(SPIM(idx))) \
836
+ : NULL, \
837
+ .clk_spec = { \
838
+ .frequency = NRF_CLOCK_CONTROL_FREQUENCY_MAX, \
839
+ },)) \
738
840
}; \
739
841
BUILD_ASSERT(!SPIM_HAS_PROP(idx, wake_gpios) || \
740
842
!(DT_GPIO_FLAGS(SPIM(idx), wake_gpios) & GPIO_ACTIVE_LOW),\
@@ -745,7 +847,7 @@ static int spi_nrfx_init(const struct device *dev)
745
847
PM_DEVICE_DT_GET(SPIM(idx)), \
746
848
&spi_##idx##_data, \
747
849
&spi_##idx##z_config, \
748
- POST_KERNEL, CONFIG_SPI_INIT_PRIORITY , \
850
+ POST_KERNEL, SPIM_INIT_PRIORITY(idx) , \
749
851
&spi_nrfx_driver_api)
750
852
751
853
#define SPIM_MEMORY_SECTION (idx ) \
0 commit comments