Skip to content

Commit 2da8e11

Browse files
Merge pull request zephyrproject-rtos#9 from converge-io/david/modem_sleep
drivers: modem: wake modem with dtr without reset
2 parents 00ee185 + ba17ace commit 2da8e11

File tree

1 file changed

+171
-8
lines changed

1 file changed

+171
-8
lines changed

drivers/modem/modem_cellular.c

Lines changed: 171 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ enum modem_cellular_state {
6060
MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT,
6161
MODEM_CELLULAR_STATE_AWAIT_REGISTERED,
6262
MODEM_CELLULAR_STATE_CARRIER_ON,
63+
MODEM_CELLULAR_STATE_ACTIVE_SLEEP,
64+
MODEM_CELLULAR_STATE_RESUME,
6365
MODEM_CELLULAR_STATE_INIT_POWER_OFF,
6466
MODEM_CELLULAR_STATE_POWER_OFF_PULSE,
6567
MODEM_CELLULAR_STATE_POWER_OFF_SCRIPT,
@@ -79,6 +81,8 @@ enum modem_cellular_event {
7981
MODEM_CELLULAR_EVENT_DEREGISTERED,
8082
MODEM_CELLULAR_EVENT_BUS_OPENED,
8183
MODEM_CELLULAR_EVENT_BUS_CLOSED,
84+
MODEM_CELLULAR_EVENT_RESET,
85+
MODEM_CELLULAR_EVENT_RDY,
8286
};
8387

8488
struct modem_cellular_data {
@@ -191,6 +195,10 @@ static const char *modem_cellular_state_str(enum modem_cellular_state state)
191195
return "run dial script";
192196
case MODEM_CELLULAR_STATE_CARRIER_ON:
193197
return "carrier on";
198+
case MODEM_CELLULAR_STATE_ACTIVE_SLEEP:
199+
return "active sleep";
200+
case MODEM_CELLULAR_STATE_RESUME:
201+
return "resume";
194202
case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
195203
return "init power off";
196204
case MODEM_CELLULAR_STATE_POWER_OFF_PULSE:
@@ -231,6 +239,10 @@ static const char *modem_cellular_event_str(enum modem_cellular_event event)
231239
return "bus opened";
232240
case MODEM_CELLULAR_EVENT_BUS_CLOSED:
233241
return "bus closed";
242+
case MODEM_CELLULAR_EVENT_RESET:
243+
return "reset";
244+
case MODEM_CELLULAR_EVENT_RDY:
245+
return "ready";
234246
}
235247

236248
return "";
@@ -491,7 +503,6 @@ static void modem_cellular_chat_on_cxreg(struct modem_chat *chat, char **argv, u
491503
}
492504
}
493505

494-
495506
static void modem_cellular_chat_on_ipr(struct modem_chat *chat, char **argv, uint16_t argc, void *user_data){
496507
int rc;
497508
struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
@@ -505,10 +516,21 @@ static void modem_cellular_chat_on_ipr(struct modem_chat *chat, char **argv, uin
505516
}
506517
}
507518

519+
static void modem_cellular_chat_on_rdy(struct modem_chat *chat, char **argv, uint16_t argc,
520+
void *user_data)
521+
{
522+
struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
523+
524+
if (strcmp(argv[0], "RDY") == 0) {
525+
modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_RDY);
526+
}
527+
}
528+
508529
MODEM_CHAT_MATCH_DEFINE(ok_match, "OK", "", NULL);
509530
MODEM_CHAT_MATCH_DEFINE(ipr_match, "OK", "", modem_cellular_chat_on_ipr);
510531
MODEM_CHAT_MATCHES_DEFINE(allow_match,
511532
MODEM_CHAT_MATCH("OK", "", NULL),
533+
MODEM_CHAT_MATCH("NO CARRIER", "", NULL),
512534
MODEM_CHAT_MATCH("ERROR", "", NULL));
513535

514536
MODEM_CHAT_MATCH_DEFINE(imei_match, "", "", modem_cellular_chat_on_imei);
@@ -522,6 +544,7 @@ MODEM_CHAT_MATCH_DEFINE(cgmi_match __maybe_unused, "", "", modem_cellular_chat_o
522544
MODEM_CHAT_MATCH_DEFINE(cgmr_match __maybe_unused, "", "", modem_cellular_chat_on_cgmr);
523545

524546
MODEM_CHAT_MATCHES_DEFINE(unsol_matches,
547+
MODEM_CHAT_MATCH("RDY", ",", modem_cellular_chat_on_rdy),
525548
MODEM_CHAT_MATCH("+CREG: ", ",", modem_cellular_chat_on_cxreg),
526549
MODEM_CHAT_MATCH("+CEREG: ", ",", modem_cellular_chat_on_cxreg),
527550
MODEM_CHAT_MATCH("+CGREG: ", ",", modem_cellular_chat_on_cxreg));
@@ -625,6 +648,11 @@ static void modem_cellular_idle_event_handler(struct modem_cellular_data *data,
625648
(const struct modem_cellular_config *)data->dev->config;
626649

627650
switch (evt) {
651+
case MODEM_CELLULAR_EVENT_RESET:
652+
if (modem_cellular_gpio_is_enabled(&config->reset_gpio) && modem_cellular_gpio_is_enabled(&config->dtr_gpio)) {
653+
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RESET_PULSE);
654+
break;
655+
}
628656
case MODEM_CELLULAR_EVENT_RESUME:
629657
if (config->autostarts) {
630658
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_AWAIT_POWER_ON);
@@ -757,7 +785,11 @@ static int modem_cellular_on_await_power_on_state_enter(struct modem_cellular_da
757785
const struct modem_cellular_config *config =
758786
(const struct modem_cellular_config *)data->dev->config;
759787

760-
modem_cellular_start_timer(data, K_MSEC(config->startup_time_ms));
788+
if (modem_cellular_gpio_is_enabled(&config->reset_gpio) && modem_cellular_gpio_is_enabled(&config->dtr_gpio)) {
789+
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RUN_INIT_SCRIPT);
790+
} else {
791+
modem_cellular_start_timer(data, K_MSEC(config->startup_time_ms));
792+
}
761793
return 0;
762794
}
763795

@@ -780,6 +812,9 @@ static void modem_cellular_await_power_on_event_handler(struct modem_cellular_da
780812

781813
static int modem_cellular_on_run_init_script_state_enter(struct modem_cellular_data *data)
782814
{
815+
const struct modem_cellular_config *config =
816+
(const struct modem_cellular_config *)data->dev->config;
817+
modem_cellular_start_timer(data, K_MSEC(config->startup_time_ms));
783818
modem_pipe_attach(data->uart_pipe, modem_cellular_bus_pipe_handler, data);
784819
return modem_pipe_open_async(data->uart_pipe);
785820
}
@@ -793,6 +828,10 @@ static void modem_cellular_run_init_script_event_handler(struct modem_cellular_d
793828
switch (evt) {
794829
case MODEM_CELLULAR_EVENT_BUS_OPENED:
795830
modem_chat_attach(&data->chat, data->uart_pipe);
831+
break;
832+
833+
case MODEM_CELLULAR_EVENT_TIMEOUT:
834+
case MODEM_CELLULAR_EVENT_RDY:
796835
modem_chat_run_script_async(&data->chat, config->init_chat_script);
797836
break;
798837

@@ -947,6 +986,10 @@ static void modem_cellular_run_dial_script_event_handler(struct modem_cellular_d
947986
modem_chat_run_script_async(&data->chat, config->dial_chat_script);
948987
break;
949988

989+
case MODEM_CELLULAR_EVENT_SCRIPT_FAILED:
990+
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RESET_PULSE);
991+
break;
992+
950993
case MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS:
951994
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_AWAIT_REGISTERED);
952995
break;
@@ -1039,7 +1082,11 @@ static void modem_cellular_carrier_on_event_handler(struct modem_cellular_data *
10391082
break;
10401083

10411084
case MODEM_CELLULAR_EVENT_SUSPEND:
1042-
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_INIT_POWER_OFF);
1085+
if (modem_cellular_gpio_is_enabled(&config->dtr_gpio)) {
1086+
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_ACTIVE_SLEEP);
1087+
} else {
1088+
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_INIT_POWER_OFF);
1089+
}
10431090
break;
10441091

10451092
default:
@@ -1049,13 +1096,104 @@ static void modem_cellular_carrier_on_event_handler(struct modem_cellular_data *
10491096

10501097
static int modem_cellular_on_carrier_on_state_leave(struct modem_cellular_data *data)
10511098
{
1099+
const struct modem_cellular_config *config =
1100+
(const struct modem_cellular_config *)data->dev->config;
1101+
10521102
modem_cellular_stop_timer(data);
10531103
net_if_carrier_off(modem_ppp_get_iface(data->ppp));
1054-
modem_chat_release(&data->chat);
1104+
if (!modem_cellular_gpio_is_enabled(&config->dtr_gpio)) {
1105+
modem_chat_release(&data->chat);
1106+
}
10551107
modem_ppp_release(data->ppp);
10561108
return 0;
10571109
}
10581110

1111+
1112+
static int modem_cellular_on_active_sleep_state_enter(struct modem_cellular_data *data)
1113+
{
1114+
const struct modem_cellular_config *config =
1115+
(const struct modem_cellular_config *)data->dev->config;
1116+
1117+
modem_chat_run_script_async(&data->chat, config->power_down_script);
1118+
1119+
1120+
k_sem_give(&data->suspended_sem);
1121+
return 0;
1122+
}
1123+
1124+
static void modem_cellular_active_sleep_event_handler(struct modem_cellular_data *data,
1125+
enum modem_cellular_event evt)
1126+
{
1127+
const struct modem_cellular_config *config =
1128+
(const struct modem_cellular_config *)data->dev->config;
1129+
1130+
switch (evt) {
1131+
case MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS:
1132+
case MODEM_CELLULAR_EVENT_SCRIPT_FAILED:
1133+
if (modem_cellular_gpio_is_enabled(&config->dtr_gpio)) {
1134+
gpio_pin_set_dt(&config->dtr_gpio, 1);
1135+
}
1136+
break;
1137+
1138+
case MODEM_CELLULAR_EVENT_RESET:
1139+
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RESET_PULSE);
1140+
break;
1141+
1142+
case MODEM_CELLULAR_EVENT_RESUME:
1143+
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RESUME);
1144+
break;
1145+
1146+
case MODEM_CELLULAR_EVENT_SUSPEND:
1147+
k_sem_give(&data->suspended_sem);
1148+
break;
1149+
1150+
default:
1151+
break;
1152+
}
1153+
}
1154+
1155+
static int modem_cellular_on_active_sleep_state_leave(struct modem_cellular_data *data)
1156+
{
1157+
const struct modem_cellular_config *config =
1158+
(const struct modem_cellular_config *)data->dev->config;
1159+
1160+
k_sem_take(&data->suspended_sem, K_NO_WAIT);
1161+
1162+
if (modem_cellular_gpio_is_enabled(&config->dtr_gpio)) {
1163+
gpio_pin_set_dt(&config->dtr_gpio, 0);
1164+
}
1165+
return 0;
1166+
}
1167+
1168+
static int modem_cellular_on_resume_state_enter(struct modem_cellular_data *data)
1169+
{
1170+
modem_cellular_start_timer(data, K_MSEC(500));
1171+
1172+
return 0;
1173+
}
1174+
1175+
static void modem_cellular_resume_event_handler(struct modem_cellular_data *data,
1176+
enum modem_cellular_event evt)
1177+
{
1178+
switch (evt) {
1179+
1180+
case MODEM_CELLULAR_EVENT_TIMEOUT:
1181+
modem_cellular_notify_user_pipes_disconnected(data);
1182+
modem_chat_release(&data->chat);
1183+
modem_cmux_release(&data->cmux);
1184+
modem_pipe_close_async(data->uart_pipe);
1185+
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_CONNECT_CMUX);
1186+
break;
1187+
1188+
default:
1189+
break;
1190+
}
1191+
}
1192+
1193+
static int modem_cellular_on_resume_state_leave(struct modem_cellular_data *data)
1194+
{
1195+
return 0;
1196+
}
10591197
static int modem_cellular_on_init_power_off_state_enter(struct modem_cellular_data *data)
10601198
{
10611199
modem_cellular_start_timer(data, K_MSEC(2000));
@@ -1222,6 +1360,14 @@ static int modem_cellular_on_state_enter(struct modem_cellular_data *data)
12221360
ret = modem_cellular_on_carrier_on_state_enter(data);
12231361
break;
12241362

1363+
case MODEM_CELLULAR_STATE_ACTIVE_SLEEP:
1364+
ret = modem_cellular_on_active_sleep_state_enter(data);
1365+
break;
1366+
1367+
case MODEM_CELLULAR_STATE_RESUME:
1368+
ret = modem_cellular_on_resume_state_enter(data);
1369+
break;
1370+
12251371
case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
12261372
ret = modem_cellular_on_init_power_off_state_enter(data);
12271373
break;
@@ -1283,6 +1429,14 @@ static int modem_cellular_on_state_leave(struct modem_cellular_data *data)
12831429
ret = modem_cellular_on_carrier_on_state_leave(data);
12841430
break;
12851431

1432+
case MODEM_CELLULAR_STATE_ACTIVE_SLEEP:
1433+
ret = modem_cellular_on_active_sleep_state_leave(data);
1434+
break;
1435+
1436+
case MODEM_CELLULAR_STATE_RESUME:
1437+
ret = modem_cellular_on_resume_state_leave(data);
1438+
break;
1439+
12861440
case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
12871441
ret = modem_cellular_on_init_power_off_state_leave(data);
12881442
break;
@@ -1374,6 +1528,14 @@ static void modem_cellular_event_handler(struct modem_cellular_data *data,
13741528
modem_cellular_carrier_on_event_handler(data, evt);
13751529
break;
13761530

1531+
case MODEM_CELLULAR_STATE_ACTIVE_SLEEP:
1532+
modem_cellular_active_sleep_event_handler(data, evt);
1533+
break;
1534+
1535+
case MODEM_CELLULAR_STATE_RESUME:
1536+
modem_cellular_resume_event_handler(data, evt);
1537+
break;
1538+
13771539
case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
13781540
modem_cellular_init_power_off_event_handler(data, evt);
13791541
break;
@@ -1724,7 +1886,7 @@ static int modem_cellular_init(const struct device *dev)
17241886
}
17251887

17261888
#ifndef CONFIG_PM_DEVICE
1727-
modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_RESUME);
1889+
modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_RESET);
17281890
#else
17291891
pm_device_init_suspended(dev);
17301892
#endif /* CONFIG_PM_DEVICE */
@@ -1835,7 +1997,7 @@ MODEM_CHAT_SCRIPT_CMDS_DEFINE(
18351997
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
18361998
MODEM_CHAT_SCRIPT_CMD_RESP("AT+QCCID", qccid_match),
18371999
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1838-
MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0," STRINGIFY(CONFIG_MODEM_CMUX_BAUDRATE) ",127,10,3,30,10,2", 100));
2000+
MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0," STRINGIFY(CONFIG_MODEM_CELLULAR_CMUX_BAUDRATE) ",127,10,3,30,10,2", 100));
18392001

18402002
MODEM_CHAT_SCRIPT_DEFINE(quectel_eg25_g_init_chat_script, quectel_eg25_g_init_chat_script_cmds,
18412003
abort_matches, modem_cellular_chat_callback_handler, 10);
@@ -1853,15 +2015,16 @@ MODEM_CHAT_SCRIPT_DEFINE(quectel_eg25_g_dial_chat_script, quectel_eg25_g_dial_ch
18532015

18542016
MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_eg25_g_power_down_script_cmds,
18552017
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=0", ok_match),
1856-
MODEM_CHAT_SCRIPT_CMD_RESP("AT+QSCLK=1", ok_match),);
2018+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+QSCLK=1", ok_match),
2019+
);
18572020

18582021
MODEM_CHAT_SCRIPT_DEFINE(quectel_eg25_g_power_down_script, quectel_eg25_g_power_down_script_cmds,
18592022
dial_abort_matches, modem_cellular_chat_callback_handler, 10);
18602023

18612024
MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_eg25_g_periodic_chat_script_cmds,
18622025
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
18632026
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
1864-
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match),
2027+
MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT+CGREG?", unsol_matches),
18652028
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CSQ", csq_match));
18662029

18672030
MODEM_CHAT_SCRIPT_DEFINE(quectel_eg25_g_periodic_chat_script,

0 commit comments

Comments
 (0)