12
12
#include <zephyr/drivers/uart.h>
13
13
#include <zephyr/drivers/pinctrl.h>
14
14
#include <zephyr/irq.h>
15
+ #include <zephyr/pm/device.h>
16
+ #include <zephyr/pm/policy.h>
17
+ #include <zephyr/sys/atomic.h>
15
18
16
19
#include <errno.h>
17
20
@@ -52,6 +55,12 @@ struct uart_cc23x0_config {
52
55
#endif
53
56
};
54
57
58
+ enum uart_cc23x0_pm_locks {
59
+ UART_CC23X0_PM_LOCK_TX ,
60
+ UART_CC23X0_PM_LOCK_RX ,
61
+ UART_CC23X0_PM_LOCK_COUNT ,
62
+ };
63
+
55
64
struct uart_cc23x0_data {
56
65
struct uart_config uart_config ;
57
66
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
@@ -74,8 +83,33 @@ struct uart_cc23x0_data {
74
83
uint8_t * rx_next_buf ;
75
84
size_t rx_next_len ;
76
85
#endif /* CONFIG_UART_CC23X0_DMA_DRIVEN */
86
+ #ifdef CONFIG_PM
87
+ ATOMIC_DEFINE (pm_lock , UART_CC23X0_PM_LOCK_COUNT );
88
+ #endif
77
89
};
78
90
91
+ static inline void uart_cc23x0_pm_policy_state_lock_get (struct uart_cc23x0_data * data ,
92
+ enum uart_cc23x0_pm_locks pm_lock_type )
93
+ {
94
+ #ifdef CONFIG_PM_DEVICE
95
+ if (!atomic_test_and_set_bit (data -> pm_lock , pm_lock_type )) {
96
+ pm_policy_state_lock_get (PM_STATE_RUNTIME_IDLE , PM_ALL_SUBSTATES );
97
+ pm_policy_state_lock_get (PM_STATE_STANDBY , PM_ALL_SUBSTATES );
98
+ }
99
+ #endif
100
+ }
101
+
102
+ static inline void uart_cc23x0_pm_policy_state_lock_put (struct uart_cc23x0_data * data ,
103
+ enum uart_cc23x0_pm_locks pm_lock_type )
104
+ {
105
+ #ifdef CONFIG_PM_DEVICE
106
+ if (atomic_test_and_clear_bit (data -> pm_lock , pm_lock_type )) {
107
+ pm_policy_state_lock_put (PM_STATE_STANDBY , PM_ALL_SUBSTATES );
108
+ pm_policy_state_lock_put (PM_STATE_RUNTIME_IDLE , PM_ALL_SUBSTATES );
109
+ }
110
+ #endif
111
+ }
112
+
79
113
static int uart_cc23x0_poll_in (const struct device * dev , unsigned char * c )
80
114
{
81
115
const struct uart_cc23x0_config * config = dev -> config ;
@@ -94,6 +128,14 @@ static void uart_cc23x0_poll_out(const struct device *dev, unsigned char c)
94
128
const struct uart_cc23x0_config * config = dev -> config ;
95
129
96
130
UARTPutChar (config -> reg , c );
131
+
132
+ #ifdef CONFIG_PM_DEVICE
133
+ /* Wait for character to be transmitted to ensure CPU
134
+ * does not enter standby when UART is busy
135
+ */
136
+ while (UARTBusy (config -> reg )) {
137
+ }
138
+ #endif
97
139
}
98
140
99
141
static int uart_cc23x0_err_check (const struct device * dev )
@@ -254,6 +296,11 @@ static void uart_cc23x0_irq_tx_enable(const struct device *dev)
254
296
{
255
297
const struct uart_cc23x0_config * config = dev -> config ;
256
298
299
+ /* When TX IRQ is enabled, it is implicit that we are expecting to transmit
300
+ * using the UART, hence we should no longer go into standby
301
+ */
302
+ uart_cc23x0_pm_policy_state_lock_get (dev -> data , UART_CC23X0_PM_LOCK_TX );
303
+
257
304
UARTEnableInt (config -> reg , UART_INT_TX );
258
305
}
259
306
@@ -262,6 +309,8 @@ static void uart_cc23x0_irq_tx_disable(const struct device *dev)
262
309
const struct uart_cc23x0_config * config = dev -> config ;
263
310
264
311
UARTDisableInt (config -> reg , UART_INT_TX );
312
+
313
+ uart_cc23x0_pm_policy_state_lock_put (dev -> data , UART_CC23X0_PM_LOCK_TX );
265
314
}
266
315
267
316
static int uart_cc23x0_irq_tx_ready (const struct device * dev )
@@ -275,6 +324,11 @@ static void uart_cc23x0_irq_rx_enable(const struct device *dev)
275
324
{
276
325
const struct uart_cc23x0_config * config = dev -> config ;
277
326
327
+ /* When RX IRQ is enabled, it is implicit that we are expecting to receive
328
+ * from the UART, hence we can no longer go into standby
329
+ */
330
+ uart_cc23x0_pm_policy_state_lock_get (dev -> data , UART_CC23X0_PM_LOCK_RX );
331
+
278
332
/* Trigger the ISR on both RX and Receive Timeout. This is to allow
279
333
* the use of the hardware FIFOs for more efficient operation
280
334
*/
@@ -286,6 +340,8 @@ static void uart_cc23x0_irq_rx_disable(const struct device *dev)
286
340
const struct uart_cc23x0_config * config = dev -> config ;
287
341
288
342
UARTDisableInt (config -> reg , UART_INT_RX | UART_INT_RT );
343
+
344
+ uart_cc23x0_pm_policy_state_lock_put (dev -> data , UART_CC23X0_PM_LOCK_RX );
289
345
}
290
346
291
347
static int uart_cc23x0_irq_tx_complete (const struct device * dev )
@@ -420,6 +476,9 @@ static int uart_cc23x0_async_tx(const struct device *dev, const uint8_t *buf, si
420
476
return ret ;
421
477
}
422
478
479
+ /* Lock PM */
480
+ uart_cc23x0_pm_policy_state_lock_get (data , UART_CC23X0_PM_LOCK_TX );
481
+
423
482
/* Enable DMA trigger to start the transfer */
424
483
UARTEnableDMA (config -> reg , UART_DMA_TX );
425
484
@@ -457,6 +516,9 @@ static int uart_cc23x0_tx_halt(struct uart_cc23x0_data *data)
457
516
if (data -> async_callback ) {
458
517
data -> async_callback (data -> dev , & evt , data -> async_user_data );
459
518
}
519
+
520
+ /* Unlock PM */
521
+ uart_cc23x0_pm_policy_state_lock_put (data , UART_CC23X0_PM_LOCK_TX );
460
522
} else {
461
523
return - EINVAL ;
462
524
}
@@ -536,6 +598,9 @@ static int uart_cc23x0_async_rx_enable(const struct device *dev, uint8_t *buf, s
536
598
goto unlock ;
537
599
}
538
600
601
+ /* Lock PM */
602
+ uart_cc23x0_pm_policy_state_lock_get (data , UART_CC23X0_PM_LOCK_RX );
603
+
539
604
/* Enable DMA trigger to start the transfer */
540
605
UARTEnableDMA (config -> reg , UART_DMA_RX );
541
606
@@ -621,6 +686,9 @@ static int uart_cc23x0_async_rx_disable(const struct device *dev)
621
686
622
687
dma_stop (config -> dma_dev , config -> dma_channel_rx );
623
688
689
+ /* Unlock PM */
690
+ uart_cc23x0_pm_policy_state_lock_put (data , UART_CC23X0_PM_LOCK_RX );
691
+
624
692
if (dma_get_status (config -> dma_dev , config -> dma_channel_rx , & status ) == 0 &&
625
693
status .pending_length ) {
626
694
rx_processed = data -> rx_len - status .pending_length ;
@@ -704,6 +772,9 @@ static void uart_cc23x0_isr(const struct device *dev)
704
772
data -> tx_buf = NULL ;
705
773
data -> tx_len = 0 ;
706
774
775
+ /* Unlock PM */
776
+ uart_cc23x0_pm_policy_state_lock_put (data , UART_CC23X0_PM_LOCK_TX );
777
+
707
778
irq_unlock (key );
708
779
709
780
UARTClearInt (config -> reg , UART_INT_TXDMADONE );
@@ -731,6 +802,9 @@ static void uart_cc23x0_isr(const struct device *dev)
731
802
732
803
data -> async_callback (dev , & evt , data -> async_user_data );
733
804
}
805
+
806
+ /* Unlock PM */
807
+ uart_cc23x0_pm_policy_state_lock_put (data , UART_CC23X0_PM_LOCK_RX );
734
808
} else {
735
809
/* Otherwise, load next buffer and start the transfer */
736
810
data -> rx_buf = data -> rx_next_buf ;
@@ -798,8 +872,6 @@ static DEVICE_API(uart, uart_cc23x0_driver_api) = {
798
872
799
873
#if CONFIG_UART_INTERRUPT_DRIVEN || CONFIG_UART_CC23X0_DMA_DRIVEN
800
874
#define UART_CC23X0_IRQ_CFG (n ) \
801
- const struct uart_cc23x0_config *config = dev->config; \
802
- \
803
875
do { \
804
876
UARTClearInt(config->reg, UART_INT_RX); \
805
877
UARTClearInt(config->reg, UART_INT_RT); \
@@ -832,17 +904,13 @@ static DEVICE_API(uart, uart_cc23x0_driver_api) = {
832
904
833
905
static int uart_cc23x0_init_common (const struct device * dev )
834
906
{
907
+ #ifdef CONFIG_UART_CC23X0_DMA_DRIVEN
835
908
const struct uart_cc23x0_config * config = dev -> config ;
909
+ #endif
836
910
struct uart_cc23x0_data * data = dev -> data ;
837
- int ret ;
838
911
839
912
CLKCTLEnable (CLKCTL_BASE , CLKCTL_UART0 );
840
913
841
- ret = pinctrl_apply_state (config -> pcfg , PINCTRL_STATE_DEFAULT );
842
- if (ret < 0 ) {
843
- return ret ;
844
- }
845
-
846
914
#ifdef CONFIG_UART_CC23X0_DMA_DRIVEN
847
915
if (!device_is_ready (config -> dma_dev )) {
848
916
return - ENODEV ;
@@ -855,34 +923,66 @@ static int uart_cc23x0_init_common(const struct device *dev)
855
923
data -> dev = dev ;
856
924
#endif
857
925
926
+ #ifdef CONFIG_PM_DEVICE
927
+ atomic_clear_bit (data -> pm_lock , UART_CC23X0_PM_LOCK_RX );
928
+ atomic_clear_bit (data -> pm_lock , UART_CC23X0_PM_LOCK_TX );
929
+ #endif
930
+
858
931
/* Configure and enable UART */
859
932
return uart_cc23x0_configure (dev , & data -> uart_config );
860
933
}
861
934
935
+ #ifdef CONFIG_PM_DEVICE
936
+
937
+ static int uart_cc23x0_pm_action (const struct device * dev , enum pm_device_action action )
938
+ {
939
+ const struct uart_cc23x0_config * config = dev -> config ;
940
+
941
+ switch (action ) {
942
+ case PM_DEVICE_ACTION_SUSPEND :
943
+ UARTDisable (config -> reg );
944
+ CLKCTLDisable (CLKCTL_BASE , CLKCTL_UART0 );
945
+ return 0 ;
946
+ case PM_DEVICE_ACTION_RESUME :
947
+ return uart_cc23x0_init_common (dev );
948
+ default :
949
+ return - ENOTSUP ;
950
+ }
951
+ }
952
+
953
+ #endif /* CONFIG_PM_DEVICE */
954
+
862
955
#define UART_CC23X0_DEVICE_DEFINE (n ) \
863
956
\
864
- DEVICE_DT_INST_DEFINE(n, uart_cc23x0_init_##n, NULL, &uart_cc23x0_data_##n, \
865
- &uart_cc23x0_config_ ##n, PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \
866
- &uart_cc23x0_driver_api)
957
+ DEVICE_DT_INST_DEFINE(n, uart_cc23x0_init_##n, PM_DEVICE_DT_INST_GET(n), \
958
+ &uart_cc23x0_data_ ##n, &uart_cc23x0_config_##n, \
959
+ PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, &uart_cc23x0_driver_api)
867
960
868
961
#define UART_CC23X0_INIT_FUNC (n ) \
869
962
static int uart_cc23x0_init_##n(const struct device *dev) \
870
963
{ \
964
+ const struct uart_cc23x0_config *config = dev->config; \
871
965
int ret; \
872
966
\
967
+ ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); \
968
+ if (ret) { \
969
+ return ret; \
970
+ } \
971
+ \
873
972
ret = uart_cc23x0_init_common(dev); \
874
- if (ret < 0 ) { \
973
+ if (ret) { \
875
974
return ret; \
876
975
} \
877
976
\
878
977
/* Enable interrupts */ \
879
978
UART_CC23X0_IRQ_CFG (n ); \
880
979
\
881
- return ret ; \
980
+ return 0 ; \
882
981
}
883
982
884
983
#define UART_CC23X0_INIT (n ) \
885
984
PINCTRL_DT_INST_DEFINE(n); \
985
+ PM_DEVICE_DT_INST_DEFINE(n, uart_cc23x0_pm_action); \
886
986
UART_CC23X0_INIT_FUNC(n); \
887
987
\
888
988
static struct uart_cc23x0_config uart_cc23x0_config_##n = { \
0 commit comments