Skip to content

Commit e588ce6

Browse files
committed
app: Add overlay for mdm-power-gpios
Adds overlay overlay-zephyr-modem.overlay for mdm-power-gpios, so that Cellular Modem driver, which does not currently support DTR, can power on and power off Serial Modem. Kconfig CONFIG_SM_START_SLEEP removed. Serial Modem Will start from sleep if mdm-power-gpios is included. Signed-off-by: Markus Lassila <markus.lassila@nordicsemi.no>
1 parent 1f9783b commit e588ce6

8 files changed

Lines changed: 152 additions & 63 deletions

File tree

app/Kconfig

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,6 @@ config SM_UART_TX_BUF_SIZE
7979
If the buffers are full, will send synchronously.
8080
These buffers are not used when CMUX is in use.
8181

82-
#
83-
# GPIO functionality
84-
#
85-
config SM_START_SLEEP
86-
bool "Enter sleep on startup"
87-
help
88-
If enabled, the SiP is put into deep sleep when powered on.
89-
TODO: DTR to wake up from sleep is not implemented yet.
90-
9182
#
9283
# Automatic network attach
9384
#

app/overlay-zephyr-modem.conf

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,5 @@
44
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
55
#
66

7-
# The nRF91 is power-managed by Zephyr's modem_cellular driver running on the other chip.
8-
CONFIG_SM_START_SLEEP=y
9-
107
# Compatibility with cellular modem driver.
118
CONFIG_SM_MODEM_CELLULAR=y

app/overlay-zephyr-modem.overlay

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
/ {
8+
chosen {
9+
ncs,sm-power-key = &power_key;
10+
};
11+
};
12+
13+
&dtr_uart2 {
14+
/* Currently Cellular Modem driver does not drive DTR, so set it always active */
15+
dtr-gpios = <&gpio0 31 (GPIO_PULL_DOWN | GPIO_ACTIVE_LOW)>;
16+
};
17+
/ {
18+
power_key: sm-power-key {
19+
compatible = "nordic,sm-power-key";
20+
gpios = <&gpio0 22 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
21+
status = "okay";
22+
};
23+
};
24+
25+
&gpio0 {
26+
status = "okay";
27+
/* Use PORT events to save power */
28+
sense-edge-mask = <0xFFFFFFFF>;
29+
};

app/sample.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,8 @@ tests:
136136
build_only: true
137137
extra_args:
138138
- EXTRA_CONF_FILE="overlay-cmux.conf;overlay-ppp.conf;overlay-zephyr-modem.conf"
139-
- EXTRA_DTC_OVERLAY_FILE="overlay-external-mcu.overlay"
139+
- EXTRA_DTC_OVERLAY_FILE="overlay-external-mcu.overlay;overlay-zephyr-modem.overlay"
140140
platform_allow:
141-
- nrf9160dk/nrf9160/ns
142141
- nrf9161dk/nrf9161/ns
143142
- nrf9151dk/nrf9151/ns
144143
integration_platforms:

app/src/main.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,11 @@ int start_execute(void)
202202

203203
LOG_INF("Serial Modem");
204204

205-
sm_ctrl_pin_init();
205+
err = sm_ctrl_pin_init();
206+
if (err) {
207+
LOG_ERR("Failed to init ctrl_pin: %d", err);
208+
return err;
209+
}
206210

207211
/* This will send "READY" or "INIT ERROR" to UART so after this nothing
208212
* should be done that can fail
@@ -228,6 +232,8 @@ int main(void)
228232
nrf_power_resetreas_clear(NRF_POWER_NS, 0x70017);
229233
LOG_DBG("RR: 0x%08x", rr);
230234

235+
sm_ctrl_pin_init_gpios();
236+
231237
/* Init and load settings */
232238
if (sm_settings_init() != 0) {
233239
LOG_WRN("Failed to init sm settings");
@@ -254,13 +260,12 @@ int main(void)
254260

255261
check_app_fota_status();
256262

257-
#if defined(CONFIG_SM_START_SLEEP)
258-
263+
#if DT_HAS_CHOSEN(ncs_sm_power_key)
259264
if (!(rr & NRF_POWER_RESETREAS_OFF_MASK)) { /* DETECT signal from GPIO */
260265

261-
sm_ctrl_pin_enter_sleep_no_uninit();
266+
sm_ctrl_pin_enter_sleep_no_uninit(true);
262267
}
263-
#endif /* CONFIG_SM_START_SLEEP */
268+
#endif
264269

265270
ret = start_execute();
266271
exit:

app/src/sm_ctrl_pin.c

Lines changed: 91 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,20 @@
1818

1919
LOG_MODULE_REGISTER(sm_ctrl_pin, CONFIG_SM_LOG_LEVEL);
2020

21-
#if DT_NODE_HAS_PROP(DT_CHOSEN(ncs_sm_uart), dtr_gpios)
21+
#define SM_DTR_GPIOS DT_NODE_HAS_PROP(DT_CHOSEN(ncs_sm_uart), dtr_gpios)
22+
#define SM_HAS_PWR_KEY DT_HAS_CHOSEN(ncs_sm_power_key)
23+
24+
#if SM_DTR_GPIOS
2225
static const struct gpio_dt_spec dtr_gpio =
2326
GPIO_DT_SPEC_GET_OR(DT_CHOSEN(ncs_sm_uart), dtr_gpios, {0});
2427

25-
static struct gpio_callback gpio_cb;
28+
static struct gpio_callback dtr_gpio_cb;
29+
#endif
30+
#if SM_HAS_PWR_KEY
31+
static const struct gpio_dt_spec mdm_pwr_gpio =
32+
GPIO_DT_SPEC_GET_OR(DT_CHOSEN(ncs_sm_power_key), gpios, {0});
33+
34+
static struct gpio_callback mdm_pwr_gpio_cb;
2635
#endif
2736

2837
static int ext_xtal_control(bool xtal_on)
@@ -58,7 +67,7 @@ static int ext_xtal_control(bool xtal_on)
5867
return err;
5968
}
6069

61-
#if DT_NODE_HAS_PROP(DT_CHOSEN(ncs_sm_uart), dtr_gpios)
70+
#if SM_DTR_GPIOS
6271
static void dtr_enable_fn(struct k_work *)
6372
{
6473
LOG_INF("DTR pin callback work function.");
@@ -82,7 +91,7 @@ static void dtr_pin_callback(const struct device *dev, struct gpio_callback *gpi
8291

8392
int sm_ctrl_pin_ready(void)
8493
{
85-
#if DT_NODE_HAS_PROP(DT_CHOSEN(ncs_sm_uart), dtr_gpios)
94+
#if SM_DTR_GPIOS
8695
if (gpio_is_ready_dt(&dtr_gpio)) {
8796
return 0;
8897
}
@@ -91,31 +100,15 @@ int sm_ctrl_pin_ready(void)
91100
return -EFAULT;
92101
}
93102

94-
void sm_ctrl_pin_enter_sleep(void)
103+
void sm_ctrl_pin_enter_sleep_no_uninit(bool at_host_power_off)
95104
{
96-
#if DT_NODE_HAS_PROP(DT_CHOSEN(ncs_sm_uart), dtr_gpios)
97-
int err;
98-
99-
err = sm_ctrl_pin_ready();
100-
if (err) {
101-
return;
102-
}
103-
104-
/* Stop threads, uninitialize host and disable DTR UART. */
105-
sm_at_host_uninit();
106-
107-
/* Only power off the modem if it has not been put
108-
* in flight mode to allow reducing NVM wear.
109-
*/
110-
if (!sm_is_modem_functional_mode(LTE_LC_FUNC_MODE_OFFLINE)) {
111-
sm_power_off_modem();
105+
#if SM_DTR_GPIOS || SM_HAS_PWR_KEY
106+
if (at_host_power_off) {
107+
sm_at_host_power_off();
112108
}
113109

114-
gpio_pin_interrupt_configure_dt(&dtr_gpio, GPIO_INT_DISABLE);
115-
116-
LOG_INF("Entering sleep.");
110+
LOG_INF("Entering sleep. No uninit.");
117111
LOG_PANIC();
118-
nrf_gpio_cfg_sense_set(dtr_gpio.pin, NRF_GPIO_PIN_SENSE_LOW);
119112

120113
k_sleep(K_MSEC(100));
121114

@@ -124,26 +117,27 @@ void sm_ctrl_pin_enter_sleep(void)
124117
#endif
125118
}
126119

127-
/* TODO: Cellular modem driver uses pulse triggered power management, which is not suitable with
128-
* the current implementation.
129-
*/
130-
void sm_ctrl_pin_enter_sleep_no_uninit(void)
120+
void sm_ctrl_pin_enter_sleep(void)
131121
{
132-
#if DT_NODE_HAS_PROP(DT_CHOSEN(ncs_sm_uart), dtr_gpios)
133-
LOG_INF("Entering sleep.");
134-
LOG_PANIC();
135-
nrf_gpio_cfg_sense_set(dtr_gpio.pin, NRF_GPIO_PIN_SENSE_LOW);
122+
#if SM_DTR_GPIOS || SM_HAS_PWR_KEY
136123

137-
k_sleep(K_MSEC(100));
124+
/* Stop threads, uninitialize host and disable DTR UART. */
125+
sm_at_host_uninit();
138126

139-
nrf_regulators_system_off(NRF_REGULATORS_NS);
140-
assert(false);
127+
/* Only power off the modem if it has not been put
128+
* in flight mode to allow reducing NVM wear.
129+
*/
130+
if (!sm_is_modem_functional_mode(LTE_LC_FUNC_MODE_OFFLINE)) {
131+
sm_power_off_modem();
132+
}
133+
134+
sm_ctrl_pin_enter_sleep_no_uninit(false);
141135
#endif
142136
}
143137

144138
void sm_ctrl_pin_enter_idle(void)
145139
{
146-
#if DT_NODE_HAS_PROP(DT_CHOSEN(ncs_sm_uart), dtr_gpios)
140+
#if SM_DTR_GPIOS
147141
LOG_INF("Entering idle.");
148142
int err;
149143

@@ -152,8 +146,8 @@ void sm_ctrl_pin_enter_idle(void)
152146
return;
153147
}
154148

155-
gpio_init_callback(&gpio_cb, dtr_pin_callback, BIT(dtr_gpio.pin));
156-
err = gpio_add_callback_dt(&dtr_gpio, &gpio_cb);
149+
gpio_init_callback(&dtr_gpio_cb, dtr_pin_callback, BIT(dtr_gpio.pin));
150+
err = gpio_add_callback_dt(&dtr_gpio, &dtr_gpio_cb);
157151
if (err) {
158152
LOG_ERR("gpio_add_callback failed: %d", err);
159153
return;
@@ -175,15 +169,70 @@ void sm_ctrl_pin_enter_shutdown(void)
175169
assert(false);
176170
}
177171

172+
void sm_ctrl_pin_init_gpios(void)
173+
{
174+
#if SM_DTR_GPIOS
175+
nrf_gpio_cfg_sense_set(dtr_gpio.pin, NRF_GPIO_PIN_SENSE_LOW);
176+
#endif
177+
178+
#if SM_HAS_PWR_KEY
179+
/* Configure Modem Power GPIO */
180+
if (!gpio_is_ready_dt(&mdm_pwr_gpio)) {
181+
LOG_ERR("Modem Power GPIO not ready");
182+
return;
183+
}
184+
int err = gpio_pin_configure_dt(&mdm_pwr_gpio, GPIO_INPUT);
185+
186+
if (err < 0) {
187+
LOG_ERR("Failed to configure Modem Power GPIO (%d).", err);
188+
return;
189+
}
190+
nrf_gpio_cfg_sense_set(mdm_pwr_gpio.pin, NRF_GPIO_PIN_SENSE_LOW);
191+
#endif
192+
}
193+
194+
195+
#if SM_HAS_PWR_KEY
196+
static void pwr_pin_fn(struct k_work *)
197+
{
198+
nrf_gpio_cfg_sense_set(mdm_pwr_gpio.pin, NRF_GPIO_PIN_SENSE_LOW);
199+
sm_ctrl_pin_enter_sleep();
200+
}
201+
202+
static void pwr_pin_callback(const struct device *dev, struct gpio_callback *gpio_callback,
203+
uint32_t)
204+
{
205+
static K_WORK_DELAYABLE_DEFINE(work, pwr_pin_fn);
206+
207+
k_work_reschedule(&work, K_MSEC(10));
208+
}
209+
#endif
210+
178211
int sm_ctrl_pin_init(void)
179212
{
180213
int err;
181214

182215
err = ext_xtal_control(true);
183-
if (err < 0) {
216+
if (err) {
184217
LOG_ERR("Failed to enable ext XTAL: %d", err);
185218
return err;
186219
}
187-
188-
return err;
220+
#if SM_HAS_PWR_KEY
221+
if (!gpio_is_ready_dt(&mdm_pwr_gpio)) {
222+
LOG_ERR("Modem Power GPIO not ready");
223+
return -ENODEV;
224+
}
225+
err = gpio_pin_interrupt_configure_dt(&mdm_pwr_gpio, GPIO_INT_EDGE_TO_ACTIVE);
226+
if (err) {
227+
LOG_ERR("Failed to configure Modem Power GPIO interrupt (%d).", err);
228+
return err;
229+
}
230+
gpio_init_callback(&mdm_pwr_gpio_cb, pwr_pin_callback, BIT(mdm_pwr_gpio.pin));
231+
err = gpio_add_callback_dt(&mdm_pwr_gpio, &mdm_pwr_gpio_cb);
232+
if (err) {
233+
LOG_ERR("Failed to add Modem Power GPIO callback (%d).", err);
234+
return err;
235+
}
236+
#endif
237+
return 0;
189238
}

app/src/sm_ctrl_pin.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,22 +32,28 @@ void sm_ctrl_pin_enter_sleep(void);
3232

3333
/**
3434
* @brief Enter sleep without uninitializing AT host.
35+
*
36+
* @param at_host_power_off If true, power off AT host before entering sleep.
3537
*/
36-
void sm_ctrl_pin_enter_sleep_no_uninit(void);
38+
void sm_ctrl_pin_enter_sleep_no_uninit(bool at_host_power_off);
3739

3840
/**
3941
* @brief nRF91 Series SiP enters System OFF mode.
4042
*/
4143
void sm_ctrl_pin_enter_shutdown(void);
4244

45+
/**
46+
* @brief Initialize Serial Modem control pins.
47+
*/
48+
void sm_ctrl_pin_init_gpios(void);
49+
4350
/**
4451
* @brief Initialize Serial Modem control pin module.
4552
*
4653
* @retval 0 on success, nonzero otherwise.
4754
*/
4855
int sm_ctrl_pin_init(void);
4956

50-
5157
/** @} */
5258

5359
#endif /* SM_CTRL_PIN_ */
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright (c) 2025 Nordic Semiconductor ASA
2+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
3+
4+
description: |
5+
Serial Modem power pin for Zephyr Modem.
6+
7+
compatible: "nordic,sm-power-key"
8+
9+
properties:
10+
gpios:
11+
type: phandle-array
12+
description: Input. Power GPIO pin.
13+
required: true

0 commit comments

Comments
 (0)