@@ -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,31 @@ 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+ if (IS_ENABLED (CONFIG_ZERO_LATENCY_IRQS )) {
41+ mcu_critical_state = __get_PRIMASK ();
42+ __disable_irq ();
43+ } else {
44+ mcu_critical_state = irq_lock ();
45+ }
46+
47+ return mcu_critical_state ;
48+ }
49+
50+ static void full_irq_unlock (uint32_t mcu_critical_state )
51+ {
52+ if (IS_ENABLED (CONFIG_ZERO_LATENCY_IRQS )) {
53+ __set_PRIMASK (mcu_critical_state );
54+ } else {
55+ irq_unlock (mcu_critical_state );
56+ }
57+ }
58+ #endif /* CONFIG_ZERO_LATENCY_IRQS */
59+
3260static void hfxo_start_up_timer_handler (struct k_timer * timer )
3361{
3462 struct dev_data_hfxo * dev_data =
@@ -48,6 +76,40 @@ static void hfxo_start_up_timer_handler(struct k_timer *timer)
4876 }
4977}
5078
79+ static void start_hfxo (struct dev_data_hfxo * dev_data )
80+ {
81+ nrf_lrcconf_event_clear (NRF_LRCCONF010 , NRF_LRCCONF_EVENT_HFXOSTARTED );
82+ soc_lrcconf_poweron_request (& dev_data -> hfxo_node , NRF_LRCCONF_POWER_MAIN );
83+ nrf_lrcconf_task_trigger (NRF_LRCCONF010 , NRF_LRCCONF_TASK_REQHFXO );
84+ }
85+
86+ static void request_hfxo (struct dev_data_hfxo * dev_data )
87+ {
88+ #if defined(CONFIG_ZERO_LATENCY_IRQS )
89+ unsigned int key ;
90+
91+ key = full_irq_lock ();
92+ if (dev_data -> request_count == 0 ) {
93+ start_hfxo (dev_data );
94+ }
95+
96+ dev_data -> request_count ++ ;
97+ full_irq_unlock (key );
98+ #else
99+ start_hfxo (dev_data );
100+ #endif /* CONFIG_ZERO_LATENCY_IRQS */
101+ }
102+
103+ #if IS_ENABLED (CONFIG_ZERO_LATENCY_IRQS )
104+ void nrf_clock_control_hfxo_request (void )
105+ {
106+ const struct device * dev = DEVICE_DT_INST_GET (0 );
107+ struct dev_data_hfxo * dev_data = dev -> data ;
108+
109+ request_hfxo (dev_data );
110+ }
111+ #endif /* CONFIG_ZERO_LATENCY_IRQS */
112+
51113static void onoff_start_hfxo (struct onoff_manager * mgr , onoff_notify_fn notify )
52114{
53115 struct dev_data_hfxo * dev_data =
@@ -56,10 +118,7 @@ static void onoff_start_hfxo(struct onoff_manager *mgr, onoff_notify_fn notify)
56118 const struct dev_config_hfxo * dev_config = dev -> config ;
57119
58120 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 );
121+ request_hfxo (dev_data );
63122
64123 /* Due to a hardware issue, the HFXOSTARTED event is currently
65124 * unreliable. Hence the timer is used to simply wait the expected
@@ -68,13 +127,53 @@ static void onoff_start_hfxo(struct onoff_manager *mgr, onoff_notify_fn notify)
68127 k_timer_start (& dev_data -> timer , dev_config -> start_up_time , K_NO_WAIT );
69128}
70129
130+ static void stop_hfxo (struct dev_data_hfxo * dev_data )
131+ {
132+ nrf_lrcconf_task_trigger (NRF_LRCCONF010 , NRF_LRCCONF_TASK_STOPREQHFXO );
133+ soc_lrcconf_poweron_release (& dev_data -> hfxo_node , NRF_LRCCONF_POWER_MAIN );
134+ }
135+
136+ static void release_hfxo (struct dev_data_hfxo * dev_data )
137+ {
138+ #if IS_ENABLED (CONFIG_ZERO_LATENCY_IRQS )
139+ unsigned int key ;
140+
141+ key = full_irq_lock ();
142+ if (dev_data -> request_count < 1 ) {
143+ full_irq_unlock (key );
144+ /* Misuse of the API, release without request? */
145+ __ASSERT_NO_MSG (false);
146+ /* In case asserts are disabled early return due to no requests pending */
147+ return ;
148+ }
149+
150+ dev_data -> request_count -- ;
151+ if (dev_data -> request_count < 1 ) {
152+ stop_hfxo (dev_data );
153+ }
154+
155+ full_irq_unlock (key );
156+ #else
157+ stop_hfxo (dev_data );
158+ #endif /* CONFIG_ZERO_LATENCY_IRQS */
159+ }
160+
161+ #if IS_ENABLED (CONFIG_ZERO_LATENCY_IRQS )
162+ void nrf_clock_control_hfxo_release (void )
163+ {
164+ const struct device * dev = DEVICE_DT_INST_GET (0 );
165+ struct dev_data_hfxo * dev_data = dev -> data ;
166+
167+ release_hfxo (dev_data );
168+ }
169+ #endif /* IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) */
170+
71171static void onoff_stop_hfxo (struct onoff_manager * mgr , onoff_notify_fn notify )
72172{
73173 struct dev_data_hfxo * dev_data =
74174 CONTAINER_OF (mgr , struct dev_data_hfxo , mgr );
75175
76- nrf_lrcconf_task_trigger (NRF_LRCCONF010 , NRF_LRCCONF_TASK_STOPREQHFXO );
77- soc_lrcconf_poweron_release (& dev_data -> hfxo_node , NRF_LRCCONF_POWER_MAIN );
176+ release_hfxo (dev_data );
78177 notify (mgr , 0 );
79178}
80179
0 commit comments