14
14
#include <zephyr/device.h>
15
15
#include <zephyr/drivers/uart.h>
16
16
#include <zephyr/drivers/clock_control.h>
17
+ #include <zephyr/pm/policy.h>
17
18
#include <zephyr/irq.h>
19
+ #include <zephyr/pm/device.h>
18
20
#include <fsl_usart.h>
19
21
#include <soc.h>
20
22
#include <fsl_device_registers.h>
@@ -86,8 +88,33 @@ struct mcux_flexcomm_data {
86
88
#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
87
89
struct uart_config uart_config ;
88
90
#endif
91
+ #ifdef CONFIG_PM_POLICY_DEVICE_CONSTRAINTS
92
+ bool pm_policy_state_lock ;
93
+ #endif
89
94
};
90
95
96
+ #ifdef CONFIG_PM_POLICY_DEVICE_CONSTRAINTS
97
+ static void mcux_flexcomm_pm_policy_state_lock_get (const struct device * dev )
98
+ {
99
+ struct mcux_flexcomm_data * data = dev -> data ;
100
+
101
+ if (!data -> pm_policy_state_lock ) {
102
+ data -> pm_policy_state_lock = true;
103
+ pm_policy_device_power_lock_get (dev );
104
+ }
105
+ }
106
+
107
+ static void mcux_flexcomm_pm_policy_state_lock_put (const struct device * dev )
108
+ {
109
+ struct mcux_flexcomm_data * data = dev -> data ;
110
+
111
+ if (data -> pm_policy_state_lock ) {
112
+ data -> pm_policy_state_lock = false;
113
+ pm_policy_device_power_lock_put (dev );
114
+ }
115
+ }
116
+ #endif
117
+
91
118
static int mcux_flexcomm_poll_in (const struct device * dev , unsigned char * c )
92
119
{
93
120
const struct mcux_flexcomm_config * config = dev -> config ;
@@ -179,6 +206,14 @@ static void mcux_flexcomm_irq_tx_enable(const struct device *dev)
179
206
const struct mcux_flexcomm_config * config = dev -> config ;
180
207
uint32_t mask = kUSART_TxLevelInterruptEnable ;
181
208
209
+ /* Indicates that this device started a transaction that should
210
+ * not be interrupted by putting the SoC in states that would
211
+ * interfere with this transfer.
212
+ */
213
+ #ifdef CONFIG_PM_POLICY_DEVICE_CONSTRAINTS
214
+ mcux_flexcomm_pm_policy_state_lock_get (dev );
215
+ #endif
216
+
182
217
USART_EnableInterrupts (config -> base , mask );
183
218
}
184
219
@@ -187,6 +222,10 @@ static void mcux_flexcomm_irq_tx_disable(const struct device *dev)
187
222
const struct mcux_flexcomm_config * config = dev -> config ;
188
223
uint32_t mask = kUSART_TxLevelInterruptEnable ;
189
224
225
+ #ifdef CONFIG_PM_POLICY_DEVICE_CONSTRAINTS
226
+ mcux_flexcomm_pm_policy_state_lock_put (dev );
227
+ #endif
228
+
190
229
USART_DisableInterrupts (config -> base , mask );
191
230
}
192
231
@@ -467,11 +506,19 @@ static int mcux_flexcomm_uart_tx(const struct device *dev, const uint8_t *buf,
467
506
/* Enable TX DMA requests */
468
507
USART_EnableTxDMA (config -> base , true);
469
508
509
+ /* Do not allow the system to suspend until the transmission has completed */
510
+ #ifdef CONFIG_PM_POLICY_DEVICE_CONSTRAINTS
511
+ mcux_flexcomm_pm_policy_state_lock_get (dev );
512
+ #endif
513
+
470
514
/* Trigger the DMA to start transfer */
471
515
ret = dma_start (config -> tx_dma .dev , config -> tx_dma .channel );
472
516
if (ret ) {
473
517
irq_unlock (key );
474
- return ret ;
518
+ #ifdef CONFIG_PM_POLICY_DEVICE_CONSTRAINTS
519
+ mcux_flexcomm_pm_policy_state_lock_put (dev );
520
+ #endif
521
+ return ret ;
475
522
}
476
523
477
524
/* Schedule a TX abort for @param timeout */
@@ -993,15 +1040,18 @@ static void mcux_flexcomm_isr(const struct device *dev)
993
1040
data -> tx_data .xfer_buf = NULL ;
994
1041
995
1042
async_user_callback (dev , & tx_done_event );
1043
+
1044
+ #ifdef CONFIG_PM_POLICY_DEVICE_CONSTRAINTS
1045
+ mcux_flexcomm_pm_policy_state_lock_put (dev );
1046
+ #endif
996
1047
}
997
1048
998
1049
}
999
1050
#endif /* CONFIG_UART_ASYNC_API */
1000
1051
}
1001
1052
#endif /* CONFIG_UART_MCUX_FLEXCOMM_ISR_SUPPORT */
1002
1053
1003
-
1004
- static int mcux_flexcomm_init (const struct device * dev )
1054
+ static int mcux_flexcomm_init_common (const struct device * dev )
1005
1055
{
1006
1056
const struct mcux_flexcomm_config * config = dev -> config ;
1007
1057
#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
@@ -1067,6 +1117,42 @@ static int mcux_flexcomm_init(const struct device *dev)
1067
1117
return 0 ;
1068
1118
}
1069
1119
1120
+ static uint32_t usart_intenset ;
1121
+ static int mcux_flexcomm_pm_action (const struct device * dev , enum pm_device_action action )
1122
+ {
1123
+ const struct mcux_flexcomm_config * config = dev -> config ;
1124
+
1125
+ usart_intenset = USART_GetEnabledInterrupts (config -> base );
1126
+
1127
+ switch (action ) {
1128
+ case PM_DEVICE_ACTION_RESUME :
1129
+ break ;
1130
+ case PM_DEVICE_ACTION_SUSPEND :
1131
+ break ;
1132
+ case PM_DEVICE_ACTION_TURN_OFF :
1133
+ break ;
1134
+ case PM_DEVICE_ACTION_TURN_ON :
1135
+ int ret = mcux_flexcomm_init_common (dev );
1136
+
1137
+ if (ret ) {
1138
+ return ret ;
1139
+ }
1140
+ USART_EnableInterrupts (config -> base , usart_intenset );
1141
+ break ;
1142
+ default :
1143
+ return - ENOTSUP ;
1144
+ }
1145
+ return 0 ;
1146
+ }
1147
+
1148
+ static int mcux_flexcomm_init (const struct device * dev )
1149
+ {
1150
+ /* Rest of the init is done from the PM_DEVICE_TURN_ON action
1151
+ * which is invoked by pm_device_driver_init().
1152
+ */
1153
+ return pm_device_driver_init (dev , mcux_flexcomm_pm_action );
1154
+ }
1155
+
1070
1156
static DEVICE_API (uart , mcux_flexcomm_driver_api ) = {
1071
1157
.poll_in = mcux_flexcomm_poll_in ,
1072
1158
.poll_out = mcux_flexcomm_poll_out ,
@@ -1202,9 +1288,11 @@ static const struct mcux_flexcomm_config mcux_flexcomm_##n##_config = { \
1202
1288
\
1203
1289
static const struct mcux_flexcomm_config mcux_flexcomm_##n##_config; \
1204
1290
\
1291
+ PM_DEVICE_DT_INST_DEFINE(n, mcux_flexcomm_pm_action); \
1292
+ \
1205
1293
DEVICE_DT_INST_DEFINE(n, \
1206
- mcux_flexcomm_init, \
1207
- NULL, \
1294
+ & mcux_flexcomm_init, \
1295
+ PM_DEVICE_DT_INST_GET(n), \
1208
1296
&mcux_flexcomm_##n##_data, \
1209
1297
&mcux_flexcomm_##n##_config, \
1210
1298
PRE_KERNEL_1, \
0 commit comments