drivers: gnss: nmea_generic: implement basic power management

As of now only the resume action is supported, and doesn't perform
any power action on the GNSS modem.
It allows to initialize the GNSS driver later than it would otherwise
be.

Also, the driver now runs a modem-specific chat script on resumption.

Signed-off-by: Tomi Fontanilles <tomi.fontanilles@nordicsemi.no>
This commit is contained in:
Tomi Fontanilles 2024-04-22 16:48:41 +03:00 committed by Anas Nashif
parent a986905df5
commit 21efdc23c9
2 changed files with 43 additions and 4 deletions

View file

@ -159,6 +159,14 @@ Flash
General Purpose I/O (GPIO)
==========================
GNSS
====
* Basic power management support has been added to the ``gnss-nmea-generic`` driver.
If ``CONFIG_PM_DEVICE=y`` the driver is now initialized in suspended mode and the
application needs to call :c:func:`pm_device_action_run` with :c:macro:`PM_DEVICE_ACTION_RESUME`
to start up the driver.
Input
=====

View file

@ -12,6 +12,7 @@
#include <zephyr/modem/backend/uart.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/pm/device.h>
#include <string.h>
#include "gnss_nmea0183.h"
@ -29,6 +30,7 @@ LOG_MODULE_REGISTER(gnss_nmea_generic, CONFIG_GNSS_LOG_LEVEL);
struct gnss_nmea_generic_config {
const struct device *uart;
const struct modem_chat_script *const init_chat_script;
};
struct gnss_nmea_generic_data {
@ -60,6 +62,7 @@ MODEM_CHAT_MATCHES_DEFINE(unsol_matches,
static int gnss_nmea_generic_resume(const struct device *dev)
{
const struct gnss_nmea_generic_config *cfg = dev->config;
struct gnss_nmea_generic_data *data = dev->data;
int ret;
@ -69,11 +72,14 @@ static int gnss_nmea_generic_resume(const struct device *dev)
}
ret = modem_chat_attach(&data->chat, data->uart_pipe);
if (ret < 0) {
modem_pipe_close(data->uart_pipe);
return ret;
if (ret == 0) {
ret = modem_chat_run_script(&data->chat, cfg->init_chat_script);
}
if (ret < 0) {
modem_pipe_close(data->uart_pipe);
}
return ret;
}
@ -148,24 +154,49 @@ static int gnss_nmea_generic_init(const struct device *dev)
return ret;
}
#if CONFIG_PM_DEVICE
pm_device_init_suspended(dev);
#else
ret = gnss_nmea_generic_resume(dev);
if (ret < 0) {
return ret;
}
#endif
return 0;
}
#if CONFIG_PM_DEVICE
static int gnss_nmea_generic_pm_action(const struct device *dev, enum pm_device_action action)
{
switch (action) {
case PM_DEVICE_ACTION_RESUME:
return gnss_nmea_generic_resume(dev);
default:
return -ENOTSUP;
}
}
#endif
#if DT_HAS_COMPAT_STATUS_OKAY(gnss_nmea_generic)
MODEM_CHAT_SCRIPT_EMPTY_DEFINE(gnss_nmea_generic_init_chat_script);
#endif
#define GNSS_NMEA_GENERIC(inst) \
static struct gnss_nmea_generic_config gnss_nmea_generic_cfg_##inst = { \
.uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \
.init_chat_script = &_CONCAT(DT_DRV_COMPAT, _init_chat_script), \
}; \
\
static struct gnss_nmea_generic_data gnss_nmea_generic_data_##inst; \
\
DEVICE_DT_INST_DEFINE(inst, gnss_nmea_generic_init, NULL, \
PM_DEVICE_DT_INST_DEFINE(inst, gnss_nmea_generic_pm_action); \
\
DEVICE_DT_INST_DEFINE(inst, gnss_nmea_generic_init, PM_DEVICE_DT_INST_GET(inst),\
&gnss_nmea_generic_data_##inst, \
&gnss_nmea_generic_cfg_##inst, \
POST_KERNEL, CONFIG_GNSS_INIT_PRIORITY, &gnss_api);
#define DT_DRV_COMPAT gnss_nmea_generic
DT_INST_FOREACH_STATUS_OKAY(GNSS_NMEA_GENERIC)
#undef DT_DRV_COMPAT