Skip to content

Commit f5b6222

Browse files
SeppoTakalorlubos
authored andcommitted
[nrf fromlist] drivers: modem: Implement runtime power management for CMUX
CMUX driver can enable the support for idle-timer in devicetree and can be requested to shut down the pipe during sleep. Then UART backend put the actual device into sleep when pipe is closed. Waking up is requested by sending data to DLC pipe or by manually opening the uart_pipe. Modem may request similar wake-up by a RING interrupt which would open the same pipe. When UART is powered and pipe is not closed, CMUX wake-up procedure is automatic. Either end may initiate the wake-up. Upstream PR #: 97362 Signed-off-by: Seppo Takalo <[email protected]>
1 parent 55c463e commit f5b6222

File tree

6 files changed

+171
-16
lines changed

6 files changed

+171
-16
lines changed

drivers/modem/modem_cellular.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include <zephyr/modem/backend/uart.h>
1818
#include <zephyr/net/ppp.h>
1919
#include <zephyr/pm/device.h>
20+
#include <zephyr/pm/device.h>
21+
#include <zephyr/pm/device_runtime.h>
2022
#include <zephyr/sys/atomic.h>
2123

2224
#include <zephyr/logging/log.h>
@@ -191,6 +193,9 @@ struct modem_cellular_config {
191193
uint16_t startup_time_ms;
192194
uint16_t shutdown_time_ms;
193195
bool autostarts;
196+
bool cmux_enable_runtime_power_save;
197+
bool cmux_close_pipe_on_power_save;
198+
k_timeout_t cmux_idle_timeout;
194199
const struct modem_chat_script *init_chat_script;
195200
const struct modem_chat_script *dial_chat_script;
196201
const struct modem_chat_script *periodic_chat_script;
@@ -2102,7 +2107,6 @@ static int modem_cellular_init(const struct device *dev)
21022107

21032108
k_mutex_init(&data->api_lock);
21042109
k_work_init_delayable(&data->timeout_work, modem_cellular_timeout_handler);
2105-
21062110
k_work_init(&data->event_dispatch_work, modem_cellular_event_dispatch_handler);
21072111
ring_buf_init(&data->event_rb, sizeof(data->event_buf), data->event_buf);
21082112

@@ -2149,6 +2153,9 @@ static int modem_cellular_init(const struct device *dev)
21492153
.receive_buf_size = ARRAY_SIZE(data->cmux_receive_buf),
21502154
.transmit_buf = data->cmux_transmit_buf,
21512155
.transmit_buf_size = ARRAY_SIZE(data->cmux_transmit_buf),
2156+
.enable_runtime_power_management = config->cmux_enable_runtime_power_save,
2157+
.close_pipe_on_power_save = config->cmux_close_pipe_on_power_save,
2158+
.idle_timeout = config->cmux_idle_timeout,
21522159
};
21532160

21542161
modem_cmux_init(&data->cmux, &cmux_config);
@@ -2886,11 +2893,8 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script,
28862893

28872894
/* Helper to define modem instance */
28882895
#define MODEM_CELLULAR_DEFINE_INSTANCE(inst, power_ms, reset_ms, startup_ms, shutdown_ms, start, \
2889-
set_baudrate_script, \
2890-
init_script, \
2891-
dial_script, \
2892-
periodic_script, \
2893-
shutdown_script) \
2896+
set_baudrate_script, init_script, dial_script, \
2897+
periodic_script, shutdown_script) \
28942898
static const struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \
28952899
.uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \
28962900
.power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \
@@ -2899,14 +2903,19 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script,
28992903
.dtr_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_dtr_gpios, {}), \
29002904
.power_pulse_duration_ms = (power_ms), \
29012905
.reset_pulse_duration_ms = (reset_ms), \
2902-
.startup_time_ms = (startup_ms), \
2906+
.startup_time_ms = (startup_ms), \
29032907
.shutdown_time_ms = (shutdown_ms), \
29042908
.autostarts = DT_INST_PROP_OR(inst, autostarts, (start)), \
2905-
.set_baudrate_chat_script = (set_baudrate_script), \
2906-
.init_chat_script = (init_script), \
2907-
.dial_chat_script = (dial_script), \
2909+
.cmux_enable_runtime_power_save = \
2910+
DT_INST_PROP_OR(inst, cmux_enable_runtime_power_save, 0), \
2911+
.cmux_close_pipe_on_power_save = \
2912+
DT_INST_PROP_OR(inst, cmux_close_pipe_on_power_save, 0), \
2913+
.cmux_idle_timeout = K_MSEC(DT_INST_PROP_OR(inst, cmux_idle_timeout_ms, 0)), \
2914+
.set_baudrate_chat_script = (set_baudrate_script), \
2915+
.init_chat_script = (init_script), \
2916+
.dial_chat_script = (dial_script), \
29082917
.periodic_chat_script = (periodic_script), \
2909-
.shutdown_chat_script = (shutdown_script), \
2918+
.shutdown_chat_script = (shutdown_script), \
29102919
.user_pipes = MODEM_CELLULAR_GET_USER_PIPES(inst), \
29112920
.user_pipes_size = ARRAY_SIZE(MODEM_CELLULAR_GET_USER_PIPES(inst)), \
29122921
}; \

dts/bindings/modem/zephyr,cellular-modem-device.yaml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,22 @@ properties:
2525
2626
Asserted (logical high) when UART is active and
2727
deasserted (logical low) when UART is inactive, powered down or in low power mode.
28+
29+
cmux-enable-runtime-power-save:
30+
type: boolean
31+
description: |
32+
Enable runtime power saving using CMUX PSC commands.
33+
This requires modem to support CMUX and PSC commands while keeping the data
34+
connection active.
35+
36+
cmux-close-pipe-on-power-save:
37+
type: boolean
38+
description: |
39+
Close the modem pipe when entering power save mode.
40+
When runtime power management is enabled, this closes the UART.
41+
This requires modem to support waking up the UART using RING signal.
42+
43+
cmux-idle-timeout-ms:
44+
type: int
45+
description: Time in milliseconds after which CMUX will enter power save mode.
46+
default: 10000

include/zephyr/modem/cmux.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,12 @@ struct modem_cmux {
159159
enum modem_cmux_state state;
160160
bool flow_control_on : 1;
161161
bool initiator : 1;
162+
/** Enable runtime power management */
163+
bool enable_runtime_power_management;
164+
/** Close pipe on power save */
165+
bool close_pipe_on_power_save;
166+
/** Idle timeout for power save */
167+
k_timeout_t idle_timeout;
162168

163169
/* Work lock */
164170
bool attached : 1;
@@ -188,10 +194,12 @@ struct modem_cmux {
188194
struct k_work_delayable transmit_work;
189195
struct k_work_delayable connect_work;
190196
struct k_work_delayable disconnect_work;
197+
struct k_work_delayable runtime_pm_work;
191198

192199
/* Synchronize actions */
193200
struct k_event event;
194201
k_timepoint_t t3_timepoint;
202+
k_timepoint_t idle_timepoint;
195203

196204
/* Statistics */
197205
#if CONFIG_MODEM_STATS
@@ -220,6 +228,12 @@ struct modem_cmux_config {
220228
uint8_t *transmit_buf;
221229
/** Size of transmit buffer in bytes [149, ...] */
222230
uint16_t transmit_buf_size;
231+
/** Enable runtime power management */
232+
bool enable_runtime_power_management;
233+
/** Close pipe on power save */
234+
bool close_pipe_on_power_save;
235+
/** Idle timeout for power save */
236+
k_timeout_t idle_timeout;
223237
};
224238

225239
/**

subsys/modem/backends/modem_backend_uart_async.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
LOG_MODULE_REGISTER(modem_backend_uart_async, CONFIG_MODEM_MODULES_LOG_LEVEL);
1212

1313
#include <zephyr/kernel.h>
14+
#include <zephyr/pm/device_runtime.h>
1415
#include <zephyr/drivers/gpio.h>
1516
#include <string.h>
1617

@@ -158,6 +159,11 @@ static int modem_backend_uart_async_open(void *data)
158159
atomic_clear(&backend->async.common.state);
159160
ring_buf_reset(&backend->async.receive_rb);
160161

162+
ret = pm_device_runtime_get(backend->uart);
163+
if (ret < 0) {
164+
LOG_ERR("Failed to power on UART: %d", ret);
165+
return ret;
166+
}
161167
if (backend->dtr_gpio) {
162168
gpio_pin_set_dt(backend->dtr_gpio, 1);
163169
}
@@ -269,13 +275,20 @@ static int modem_backend_uart_async_receive(void *data, uint8_t *buf, size_t siz
269275
static int modem_backend_uart_async_close(void *data)
270276
{
271277
struct modem_backend_uart *backend = (struct modem_backend_uart *)data;
278+
int ret;
272279

273280
atomic_clear_bit(&backend->async.common.state, MODEM_BACKEND_UART_ASYNC_STATE_OPEN_BIT);
274281
uart_tx_abort(backend->uart);
275282
uart_rx_disable(backend->uart);
276283
if (backend->dtr_gpio) {
277284
gpio_pin_set_dt(backend->dtr_gpio, 0);
278285
}
286+
ret = pm_device_runtime_put_async(backend->uart, K_NO_WAIT);
287+
if (ret < 0) {
288+
LOG_ERR("Failed to power off UART: %d", ret);
289+
return ret;
290+
}
291+
modem_pipe_notify_closed(&backend->pipe);
279292
return 0;
280293
}
281294

subsys/modem/backends/modem_backend_uart_async_hwfc.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
LOG_MODULE_REGISTER(modem_backend_uart_async_hwfc, CONFIG_MODEM_MODULES_LOG_LEVEL);
1212

1313
#include <zephyr/kernel.h>
14+
#include <zephyr/pm/device_runtime.h>
1415
#include <zephyr/drivers/gpio.h>
1516
#include <string.h>
1617

@@ -222,6 +223,11 @@ static int modem_backend_uart_async_hwfc_open(void *data)
222223
return -ENOMEM;
223224
}
224225

226+
ret = pm_device_runtime_get(backend->uart);
227+
if (ret < 0) {
228+
LOG_ERR("Failed to power on UART: %d", ret);
229+
return ret;
230+
}
225231
if (backend->dtr_gpio) {
226232
gpio_pin_set_dt(backend->dtr_gpio, 1);
227233
}
@@ -352,6 +358,7 @@ static int modem_backend_uart_async_hwfc_receive(void *data, uint8_t *buf, size_
352358
static int modem_backend_uart_async_hwfc_close(void *data)
353359
{
354360
struct modem_backend_uart *backend = (struct modem_backend_uart *)data;
361+
int ret;
355362

356363
atomic_clear_bit(&backend->async.common.state, MODEM_BACKEND_UART_ASYNC_STATE_OPEN_BIT);
357364
uart_tx_abort(backend->uart);
@@ -365,6 +372,13 @@ static int modem_backend_uart_async_hwfc_close(void *data)
365372
if (backend->dtr_gpio) {
366373
gpio_pin_set_dt(backend->dtr_gpio, 0);
367374
}
375+
ret = pm_device_runtime_put_async(backend->uart, K_NO_WAIT);
376+
if (ret < 0) {
377+
LOG_ERR("Failed to power off UART: %d", ret);
378+
return ret;
379+
}
380+
modem_pipe_notify_closed(&backend->pipe);
381+
368382
return 0;
369383
}
370384

0 commit comments

Comments
 (0)