Skip to content

Commit

Permalink
Merge pull request zephyrproject-rtos#9 from converge-io/david/modem_…
Browse files Browse the repository at this point in the history
…sleep

drivers: modem: wake modem with dtr without reset
  • Loading branch information
davidbascelli authored Aug 2, 2024
2 parents 00ee185 + ba17ace commit 2da8e11
Showing 1 changed file with 171 additions and 8 deletions.
179 changes: 171 additions & 8 deletions drivers/modem/modem_cellular.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ enum modem_cellular_state {
MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT,
MODEM_CELLULAR_STATE_AWAIT_REGISTERED,
MODEM_CELLULAR_STATE_CARRIER_ON,
MODEM_CELLULAR_STATE_ACTIVE_SLEEP,
MODEM_CELLULAR_STATE_RESUME,
MODEM_CELLULAR_STATE_INIT_POWER_OFF,
MODEM_CELLULAR_STATE_POWER_OFF_PULSE,
MODEM_CELLULAR_STATE_POWER_OFF_SCRIPT,
Expand All @@ -79,6 +81,8 @@ enum modem_cellular_event {
MODEM_CELLULAR_EVENT_DEREGISTERED,
MODEM_CELLULAR_EVENT_BUS_OPENED,
MODEM_CELLULAR_EVENT_BUS_CLOSED,
MODEM_CELLULAR_EVENT_RESET,
MODEM_CELLULAR_EVENT_RDY,
};

struct modem_cellular_data {
Expand Down Expand Up @@ -191,6 +195,10 @@ static const char *modem_cellular_state_str(enum modem_cellular_state state)
return "run dial script";
case MODEM_CELLULAR_STATE_CARRIER_ON:
return "carrier on";
case MODEM_CELLULAR_STATE_ACTIVE_SLEEP:
return "active sleep";
case MODEM_CELLULAR_STATE_RESUME:
return "resume";
case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
return "init power off";
case MODEM_CELLULAR_STATE_POWER_OFF_PULSE:
Expand Down Expand Up @@ -231,6 +239,10 @@ static const char *modem_cellular_event_str(enum modem_cellular_event event)
return "bus opened";
case MODEM_CELLULAR_EVENT_BUS_CLOSED:
return "bus closed";
case MODEM_CELLULAR_EVENT_RESET:
return "reset";
case MODEM_CELLULAR_EVENT_RDY:
return "ready";
}

return "";
Expand Down Expand Up @@ -491,7 +503,6 @@ static void modem_cellular_chat_on_cxreg(struct modem_chat *chat, char **argv, u
}
}


static void modem_cellular_chat_on_ipr(struct modem_chat *chat, char **argv, uint16_t argc, void *user_data){
int rc;
struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
Expand All @@ -505,10 +516,21 @@ static void modem_cellular_chat_on_ipr(struct modem_chat *chat, char **argv, uin
}
}

static void modem_cellular_chat_on_rdy(struct modem_chat *chat, char **argv, uint16_t argc,
void *user_data)
{
struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;

if (strcmp(argv[0], "RDY") == 0) {
modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_RDY);
}
}

MODEM_CHAT_MATCH_DEFINE(ok_match, "OK", "", NULL);
MODEM_CHAT_MATCH_DEFINE(ipr_match, "OK", "", modem_cellular_chat_on_ipr);
MODEM_CHAT_MATCHES_DEFINE(allow_match,
MODEM_CHAT_MATCH("OK", "", NULL),
MODEM_CHAT_MATCH("NO CARRIER", "", NULL),
MODEM_CHAT_MATCH("ERROR", "", NULL));

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

MODEM_CHAT_MATCHES_DEFINE(unsol_matches,
MODEM_CHAT_MATCH("RDY", ",", modem_cellular_chat_on_rdy),
MODEM_CHAT_MATCH("+CREG: ", ",", modem_cellular_chat_on_cxreg),
MODEM_CHAT_MATCH("+CEREG: ", ",", modem_cellular_chat_on_cxreg),
MODEM_CHAT_MATCH("+CGREG: ", ",", modem_cellular_chat_on_cxreg));
Expand Down Expand Up @@ -625,6 +648,11 @@ static void modem_cellular_idle_event_handler(struct modem_cellular_data *data,
(const struct modem_cellular_config *)data->dev->config;

switch (evt) {
case MODEM_CELLULAR_EVENT_RESET:
if (modem_cellular_gpio_is_enabled(&config->reset_gpio) && modem_cellular_gpio_is_enabled(&config->dtr_gpio)) {
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RESET_PULSE);
break;
}
case MODEM_CELLULAR_EVENT_RESUME:
if (config->autostarts) {
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_AWAIT_POWER_ON);
Expand Down Expand Up @@ -757,7 +785,11 @@ static int modem_cellular_on_await_power_on_state_enter(struct modem_cellular_da
const struct modem_cellular_config *config =
(const struct modem_cellular_config *)data->dev->config;

modem_cellular_start_timer(data, K_MSEC(config->startup_time_ms));
if (modem_cellular_gpio_is_enabled(&config->reset_gpio) && modem_cellular_gpio_is_enabled(&config->dtr_gpio)) {
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RUN_INIT_SCRIPT);
} else {
modem_cellular_start_timer(data, K_MSEC(config->startup_time_ms));
}
return 0;
}

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

static int modem_cellular_on_run_init_script_state_enter(struct modem_cellular_data *data)
{
const struct modem_cellular_config *config =
(const struct modem_cellular_config *)data->dev->config;
modem_cellular_start_timer(data, K_MSEC(config->startup_time_ms));
modem_pipe_attach(data->uart_pipe, modem_cellular_bus_pipe_handler, data);
return modem_pipe_open_async(data->uart_pipe);
}
Expand All @@ -793,6 +828,10 @@ static void modem_cellular_run_init_script_event_handler(struct modem_cellular_d
switch (evt) {
case MODEM_CELLULAR_EVENT_BUS_OPENED:
modem_chat_attach(&data->chat, data->uart_pipe);
break;

case MODEM_CELLULAR_EVENT_TIMEOUT:
case MODEM_CELLULAR_EVENT_RDY:
modem_chat_run_script_async(&data->chat, config->init_chat_script);
break;

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

case MODEM_CELLULAR_EVENT_SCRIPT_FAILED:
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RESET_PULSE);
break;

case MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS:
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_AWAIT_REGISTERED);
break;
Expand Down Expand Up @@ -1039,7 +1082,11 @@ static void modem_cellular_carrier_on_event_handler(struct modem_cellular_data *
break;

case MODEM_CELLULAR_EVENT_SUSPEND:
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_INIT_POWER_OFF);
if (modem_cellular_gpio_is_enabled(&config->dtr_gpio)) {
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_ACTIVE_SLEEP);
} else {
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_INIT_POWER_OFF);
}
break;

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

static int modem_cellular_on_carrier_on_state_leave(struct modem_cellular_data *data)
{
const struct modem_cellular_config *config =
(const struct modem_cellular_config *)data->dev->config;

modem_cellular_stop_timer(data);
net_if_carrier_off(modem_ppp_get_iface(data->ppp));
modem_chat_release(&data->chat);
if (!modem_cellular_gpio_is_enabled(&config->dtr_gpio)) {
modem_chat_release(&data->chat);
}
modem_ppp_release(data->ppp);
return 0;
}


static int modem_cellular_on_active_sleep_state_enter(struct modem_cellular_data *data)
{
const struct modem_cellular_config *config =
(const struct modem_cellular_config *)data->dev->config;

modem_chat_run_script_async(&data->chat, config->power_down_script);


k_sem_give(&data->suspended_sem);
return 0;
}

static void modem_cellular_active_sleep_event_handler(struct modem_cellular_data *data,
enum modem_cellular_event evt)
{
const struct modem_cellular_config *config =
(const struct modem_cellular_config *)data->dev->config;

switch (evt) {
case MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS:
case MODEM_CELLULAR_EVENT_SCRIPT_FAILED:
if (modem_cellular_gpio_is_enabled(&config->dtr_gpio)) {
gpio_pin_set_dt(&config->dtr_gpio, 1);
}
break;

case MODEM_CELLULAR_EVENT_RESET:
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RESET_PULSE);
break;

case MODEM_CELLULAR_EVENT_RESUME:
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RESUME);
break;

case MODEM_CELLULAR_EVENT_SUSPEND:
k_sem_give(&data->suspended_sem);
break;

default:
break;
}
}

static int modem_cellular_on_active_sleep_state_leave(struct modem_cellular_data *data)
{
const struct modem_cellular_config *config =
(const struct modem_cellular_config *)data->dev->config;

k_sem_take(&data->suspended_sem, K_NO_WAIT);

if (modem_cellular_gpio_is_enabled(&config->dtr_gpio)) {
gpio_pin_set_dt(&config->dtr_gpio, 0);
}
return 0;
}

static int modem_cellular_on_resume_state_enter(struct modem_cellular_data *data)
{
modem_cellular_start_timer(data, K_MSEC(500));

return 0;
}

static void modem_cellular_resume_event_handler(struct modem_cellular_data *data,
enum modem_cellular_event evt)
{
switch (evt) {

case MODEM_CELLULAR_EVENT_TIMEOUT:
modem_cellular_notify_user_pipes_disconnected(data);
modem_chat_release(&data->chat);
modem_cmux_release(&data->cmux);
modem_pipe_close_async(data->uart_pipe);
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_CONNECT_CMUX);
break;

default:
break;
}
}

static int modem_cellular_on_resume_state_leave(struct modem_cellular_data *data)
{
return 0;
}
static int modem_cellular_on_init_power_off_state_enter(struct modem_cellular_data *data)
{
modem_cellular_start_timer(data, K_MSEC(2000));
Expand Down Expand Up @@ -1222,6 +1360,14 @@ static int modem_cellular_on_state_enter(struct modem_cellular_data *data)
ret = modem_cellular_on_carrier_on_state_enter(data);
break;

case MODEM_CELLULAR_STATE_ACTIVE_SLEEP:
ret = modem_cellular_on_active_sleep_state_enter(data);
break;

case MODEM_CELLULAR_STATE_RESUME:
ret = modem_cellular_on_resume_state_enter(data);
break;

case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
ret = modem_cellular_on_init_power_off_state_enter(data);
break;
Expand Down Expand Up @@ -1283,6 +1429,14 @@ static int modem_cellular_on_state_leave(struct modem_cellular_data *data)
ret = modem_cellular_on_carrier_on_state_leave(data);
break;

case MODEM_CELLULAR_STATE_ACTIVE_SLEEP:
ret = modem_cellular_on_active_sleep_state_leave(data);
break;

case MODEM_CELLULAR_STATE_RESUME:
ret = modem_cellular_on_resume_state_leave(data);
break;

case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
ret = modem_cellular_on_init_power_off_state_leave(data);
break;
Expand Down Expand Up @@ -1374,6 +1528,14 @@ static void modem_cellular_event_handler(struct modem_cellular_data *data,
modem_cellular_carrier_on_event_handler(data, evt);
break;

case MODEM_CELLULAR_STATE_ACTIVE_SLEEP:
modem_cellular_active_sleep_event_handler(data, evt);
break;

case MODEM_CELLULAR_STATE_RESUME:
modem_cellular_resume_event_handler(data, evt);
break;

case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
modem_cellular_init_power_off_event_handler(data, evt);
break;
Expand Down Expand Up @@ -1724,7 +1886,7 @@ static int modem_cellular_init(const struct device *dev)
}

#ifndef CONFIG_PM_DEVICE
modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_RESUME);
modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_RESET);
#else
pm_device_init_suspended(dev);
#endif /* CONFIG_PM_DEVICE */
Expand Down Expand Up @@ -1835,7 +1997,7 @@ MODEM_CHAT_SCRIPT_CMDS_DEFINE(
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+QCCID", qccid_match),
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0," STRINGIFY(CONFIG_MODEM_CMUX_BAUDRATE) ",127,10,3,30,10,2", 100));
MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0," STRINGIFY(CONFIG_MODEM_CELLULAR_CMUX_BAUDRATE) ",127,10,3,30,10,2", 100));

MODEM_CHAT_SCRIPT_DEFINE(quectel_eg25_g_init_chat_script, quectel_eg25_g_init_chat_script_cmds,
abort_matches, modem_cellular_chat_callback_handler, 10);
Expand All @@ -1853,15 +2015,16 @@ MODEM_CHAT_SCRIPT_DEFINE(quectel_eg25_g_dial_chat_script, quectel_eg25_g_dial_ch

MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_eg25_g_power_down_script_cmds,
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=0", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+QSCLK=1", ok_match),);
MODEM_CHAT_SCRIPT_CMD_RESP("AT+QSCLK=1", ok_match),
);

MODEM_CHAT_SCRIPT_DEFINE(quectel_eg25_g_power_down_script, quectel_eg25_g_power_down_script_cmds,
dial_abort_matches, modem_cellular_chat_callback_handler, 10);

MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_eg25_g_periodic_chat_script_cmds,
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT+CGREG?", unsol_matches),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CSQ", csq_match));

MODEM_CHAT_SCRIPT_DEFINE(quectel_eg25_g_periodic_chat_script,
Expand Down

0 comments on commit 2da8e11

Please sign in to comment.