driver: spi: silabs_siwx91x_gspi: Add pm device support for gspi driver
This commit enables the pm device driver support
for the spi_silabs_siwx91x_gspi driver.
Signed-off-by: S Mohamed Fiaz <fiaz.mohamed@silabs.com>
diff --git a/drivers/spi/spi_silabs_siwx91x_gspi.c b/drivers/spi/spi_silabs_siwx91x_gspi.c
index 2fb7e06..9ce1e75 100644
--- a/drivers/spi/spi_silabs_siwx91x_gspi.c
+++ b/drivers/spi/spi_silabs_siwx91x_gspi.c
@@ -17,6 +17,8 @@
#include <zephyr/sys/util.h>
#include <zephyr/sys/sys_io.h>
#include <zephyr/logging/log.h>
+#include <zephyr/pm/device.h>
+#include <zephyr/pm/device_runtime.h>
#include "clock_update.h"
LOG_MODULE_REGISTER(spi_siwx91x_gspi, CONFIG_SPI_LOG_LEVEL);
@@ -209,6 +211,7 @@
spi_context_cs_control(instance_ctx, false);
spi_context_complete(instance_ctx, spi_dev, status);
+ pm_device_runtime_put_async(spi_dev, K_NO_WAIT);
}
static int gspi_siwx91x_dma_config(const struct device *dev,
@@ -533,8 +536,15 @@
struct gspi_siwx91x_data *data = dev->data;
int ret = 0;
+ ret = pm_device_runtime_get(dev);
+ if (ret < 0) {
+ return ret;
+ }
+
if (!spi_siwx91x_is_dma_enabled_instance(dev) && asynchronous) {
ret = -ENOTSUP;
+ pm_device_runtime_put(dev);
+ return ret;
}
spi_context_lock(&data->ctx, asynchronous, cb, userdata, config);
@@ -559,6 +569,7 @@
/* Perform synchronous polling transceive */
ret = gspi_siwx91x_transceive_polling_sync(dev, &data->ctx);
spi_context_unlock_unconditionally(&data->ctx);
+ pm_device_runtime_put(dev);
}
return ret;
@@ -592,35 +603,57 @@
return 0;
}
-static int gspi_siwx91x_init(const struct device *dev)
+static int gspi_siwx91x_pm_action(const struct device *dev, enum pm_device_action action)
{
const struct gspi_siwx91x_config *cfg = dev->config;
struct gspi_siwx91x_data *data = dev->data;
int ret;
- ret = clock_control_on(cfg->clock_dev, cfg->clock_subsys);
- if (ret) {
- return ret;
+ switch (action) {
+ case PM_DEVICE_ACTION_RESUME:
+ break;
+ case PM_DEVICE_ACTION_SUSPEND:
+ break;
+ case PM_DEVICE_ACTION_TURN_ON:
+ ret = clock_control_on(cfg->clock_dev, cfg->clock_subsys);
+ if (ret < 0 && ret != -EALREADY) {
+ return ret;
+ }
+
+ ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
+ if (ret < 0 && ret != -ENOENT) {
+ return ret;
+ }
+
+ ret = spi_context_cs_configure_all(&data->ctx);
+ if (ret) {
+ return ret;
+ }
+
+ spi_context_unlock_unconditionally(&data->ctx);
+
+ cfg->reg->GSPI_BUS_MODE_b.SPI_HIGH_PERFORMANCE_EN = 1;
+ cfg->reg->GSPI_CONFIG1_b.GSPI_MANUAL_CSN = 0;
+ data->ctx.config = NULL;
+ break;
+ case PM_DEVICE_ACTION_TURN_OFF:
+ ret = clock_control_off(cfg->clock_dev, cfg->clock_subsys);
+ if (ret < 0 && ret != -EALREADY) {
+ return ret;
+ }
+ break;
+ default:
+ return -ENOTSUP;
}
- ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
- if (ret) {
- return ret;
- }
-
- ret = spi_context_cs_configure_all(&data->ctx);
- if (ret) {
- return ret;
- }
-
- spi_context_unlock_unconditionally(&data->ctx);
-
- cfg->reg->GSPI_BUS_MODE_b.SPI_HIGH_PERFORMANCE_EN = 1;
- cfg->reg->GSPI_CONFIG1_b.GSPI_MANUAL_CSN = 0;
-
return 0;
}
+static int gspi_siwx91x_init(const struct device *dev)
+{
+ return pm_device_driver_init(dev, gspi_siwx91x_pm_action);
+}
+
static DEVICE_API(spi, gspi_siwx91x_driver_api) = {
.transceive = gspi_siwx91x_transceive_sync,
#ifdef CONFIG_SPI_ASYNC
@@ -662,8 +695,9 @@
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \
.mosi_overrun = (uint8_t)SPI_MOSI_OVERRUN_DT(inst), \
}; \
- DEVICE_DT_INST_DEFINE(inst, &gspi_siwx91x_init, NULL, &gspi_data_##inst, \
- &gspi_config_##inst, POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, \
- &gspi_siwx91x_driver_api);
+ PM_DEVICE_DT_INST_DEFINE(inst, gspi_siwx91x_pm_action); \
+ DEVICE_DT_INST_DEFINE(inst, &gspi_siwx91x_init, PM_DEVICE_DT_INST_GET(inst), \
+ &gspi_data_##inst, &gspi_config_##inst, POST_KERNEL, \
+ CONFIG_SPI_INIT_PRIORITY, &gspi_siwx91x_driver_api);
DT_INST_FOREACH_STATUS_OKAY(SIWX91X_GSPI_INIT)
diff --git a/dts/arm/silabs/siwg917.dtsi b/dts/arm/silabs/siwg917.dtsi
index 561e905..72ea7f7 100644
--- a/dts/arm/silabs/siwg917.dtsi
+++ b/dts/arm/silabs/siwg917.dtsi
@@ -382,6 +382,8 @@
interrupts = <46 0>;
interrupt-names = "gspi";
clocks = <&clock0 SIWX91X_CLK_GSPI>;
+ power-domains = <&siwx91x_soc_pd>;
+ zephyr,pm-device-runtime-auto;
status = "disabled";
};