@@ -21,6 +21,9 @@ struct dev_data_hfxo {
2121 onoff_notify_fn notify ;
2222 struct k_timer timer ;
2323 sys_snode_t hfxo_node ;
24+ #if defined(CONFIG_ZERO_LATENCY_IRQS )
25+ uint16_t request_count ;
26+ #endif /* CONFIG_ZERO_LATENCY_IRQS */
2427};
2528
2629struct dev_config_hfxo {
@@ -29,6 +32,23 @@ struct dev_config_hfxo {
2932 k_timeout_t start_up_time ;
3033};
3134
35+ #if defined(CONFIG_ZERO_LATENCY_IRQS )
36+ static uint32_t full_irq_lock (void )
37+ {
38+ uint32_t mcu_critical_state ;
39+
40+ mcu_critical_state = __get_PRIMASK ();
41+ __disable_irq ();
42+
43+ return mcu_critical_state ;
44+ }
45+
46+ static void full_irq_unlock (uint32_t mcu_critical_state )
47+ {
48+ __set_PRIMASK (mcu_critical_state );
49+ }
50+ #endif /* CONFIG_ZERO_LATENCY_IRQS */
51+
3252static void hfxo_start_up_timer_handler (struct k_timer * timer )
3353{
3454 struct dev_data_hfxo * dev_data =
@@ -48,6 +68,40 @@ static void hfxo_start_up_timer_handler(struct k_timer *timer)
4868 }
4969}
5070
71+ static void start_hfxo (struct dev_data_hfxo * dev_data )
72+ {
73+ nrf_lrcconf_event_clear (NRF_LRCCONF010 , NRF_LRCCONF_EVENT_HFXOSTARTED );
74+ soc_lrcconf_poweron_request (& dev_data -> hfxo_node , NRF_LRCCONF_POWER_MAIN );
75+ nrf_lrcconf_task_trigger (NRF_LRCCONF010 , NRF_LRCCONF_TASK_REQHFXO );
76+ }
77+
78+ static void request_hfxo (struct dev_data_hfxo * dev_data )
79+ {
80+ #if defined(CONFIG_ZERO_LATENCY_IRQS )
81+ unsigned int key ;
82+
83+ key = full_irq_lock ();
84+ if (dev_data -> request_count == 0 ) {
85+ start_hfxo (dev_data );
86+ }
87+
88+ dev_data -> request_count ++ ;
89+ full_irq_unlock (key );
90+ #else
91+ start_hfxo (dev_data );
92+ #endif /* CONFIG_ZERO_LATENCY_IRQS */
93+ }
94+
95+ #if IS_ENABLED (CONFIG_ZERO_LATENCY_IRQS )
96+ void nrf_clock_control_hfxo_request (void )
97+ {
98+ const struct device * dev = DEVICE_DT_INST_GET (0 );
99+ struct dev_data_hfxo * dev_data = dev -> data ;
100+
101+ request_hfxo (dev_data );
102+ }
103+ #endif /* CONFIG_ZERO_LATENCY_IRQS */
104+
51105static void onoff_start_hfxo (struct onoff_manager * mgr , onoff_notify_fn notify )
52106{
53107 struct dev_data_hfxo * dev_data =
@@ -56,10 +110,7 @@ static void onoff_start_hfxo(struct onoff_manager *mgr, onoff_notify_fn notify)
56110 const struct dev_config_hfxo * dev_config = dev -> config ;
57111
58112 dev_data -> notify = notify ;
59-
60- nrf_lrcconf_event_clear (NRF_LRCCONF010 , NRF_LRCCONF_EVENT_HFXOSTARTED );
61- soc_lrcconf_poweron_request (& dev_data -> hfxo_node , NRF_LRCCONF_POWER_MAIN );
62- nrf_lrcconf_task_trigger (NRF_LRCCONF010 , NRF_LRCCONF_TASK_REQHFXO );
113+ request_hfxo (dev_data );
63114
64115 /* Due to a hardware issue, the HFXOSTARTED event is currently
65116 * unreliable. Hence the timer is used to simply wait the expected
@@ -68,13 +119,53 @@ static void onoff_start_hfxo(struct onoff_manager *mgr, onoff_notify_fn notify)
68119 k_timer_start (& dev_data -> timer , dev_config -> start_up_time , K_NO_WAIT );
69120}
70121
122+ static void stop_hfxo (struct dev_data_hfxo * dev_data )
123+ {
124+ nrf_lrcconf_task_trigger (NRF_LRCCONF010 , NRF_LRCCONF_TASK_STOPREQHFXO );
125+ soc_lrcconf_poweron_release (& dev_data -> hfxo_node , NRF_LRCCONF_POWER_MAIN );
126+ }
127+
128+ static void release_hfxo (struct dev_data_hfxo * dev_data )
129+ {
130+ #if IS_ENABLED (CONFIG_ZERO_LATENCY_IRQS )
131+ unsigned int key ;
132+
133+ key = full_irq_lock ();
134+ if (dev_data -> request_count < 1 ) {
135+ full_irq_unlock (key );
136+ /* Misuse of the API, release without request? */
137+ __ASSERT_NO_MSG (false);
138+ /* In case asserts are disabled early return due to no requests pending */
139+ return ;
140+ }
141+
142+ dev_data -> request_count -- ;
143+ if (dev_data -> request_count < 1 ) {
144+ stop_hfxo (dev_data );
145+ }
146+
147+ full_irq_unlock (key );
148+ #else
149+ stop_hfxo (dev_data );
150+ #endif /* CONFIG_ZERO_LATENCY_IRQS */
151+ }
152+
153+ #if IS_ENABLED (CONFIG_ZERO_LATENCY_IRQS )
154+ void nrf_clock_control_hfxo_release (void )
155+ {
156+ const struct device * dev = DEVICE_DT_INST_GET (0 );
157+ struct dev_data_hfxo * dev_data = dev -> data ;
158+
159+ release_hfxo (dev_data );
160+ }
161+ #endif /* IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) */
162+
71163static void onoff_stop_hfxo (struct onoff_manager * mgr , onoff_notify_fn notify )
72164{
73165 struct dev_data_hfxo * dev_data =
74166 CONTAINER_OF (mgr , struct dev_data_hfxo , mgr );
75167
76- nrf_lrcconf_task_trigger (NRF_LRCCONF010 , NRF_LRCCONF_TASK_STOPREQHFXO );
77- soc_lrcconf_poweron_release (& dev_data -> hfxo_node , NRF_LRCCONF_POWER_MAIN );
168+ release_hfxo (dev_data );
78169 notify (mgr , 0 );
79170}
80171
0 commit comments