From 2958f691bb508e642a41b731f7df9d31ee8500e0 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Tue, 21 May 2024 19:25:47 +0300 Subject: [PATCH] drivers: mipi_dbi: smartbond: Optimize driver PM This commit should optimize the way the device is allowed to enter the suspended state. Instead of returning a PM error code to abort the PM process, the standby power state is constrained as long as the device is not allowed to enter suspension. With that approach, acquiring PD_SYS is not needed when in PM device runtime mode. Signed-off-by: Ioannis Karachalios --- drivers/mipi_dbi/mipi_dbi_smartbond.c | 64 +++++++++------------------ 1 file changed, 21 insertions(+), 43 deletions(-) diff --git a/drivers/mipi_dbi/mipi_dbi_smartbond.c b/drivers/mipi_dbi/mipi_dbi_smartbond.c index 480ee2158b2..da0e5e154ce 100644 --- a/drivers/mipi_dbi/mipi_dbi_smartbond.c +++ b/drivers/mipi_dbi/mipi_dbi_smartbond.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -62,10 +63,6 @@ struct mipi_dbi_smartbond_data { struct k_sem sync_sem; /* Flag indicating whether or not an underflow took place */ volatile bool underflow_flag; -#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) - /* Flag to designate whether or not a frame update is in progress */ - bool is_active; -#endif /* Layer settings */ lcdc_smartbond_layer_cfg layer; }; @@ -82,23 +79,20 @@ struct mipi_dbi_smartbond_config { }; /* Mark the device is is progress and so it's not allowed to enter the sleep state. */ -static void mipi_dbi_pm_get(const struct device *dev) +static inline void mipi_dbi_smartbond_pm_policy_state_lock_get(void) { -#ifdef CONFIG_PM_DEVICE - struct mipi_dbi_smartbond_data *data = dev->data; - - data->is_active = true; -#endif + /* + * Prevent the SoC from etering the normal sleep state as PDC does not support + * waking up the application core following LCDC events. + */ + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); } /* Mark that device is inactive and so it's allowed to enter the sleep state */ -static void mipi_dbi_pm_put(const struct device *dev) +static inline void mipi_dbi_smartbond_pm_policy_state_lock_put(void) { -#ifdef CONFIG_PM_DEVICE - struct mipi_dbi_smartbond_data *data = dev->data; - - data->is_active = false; -#endif + /* Allow the SoC to enter the nornmal sleep state once LCDC is inactive */ + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); } /* Helper function to trigger the LCDC fetching data from frame buffer to the connected display */ @@ -217,6 +211,8 @@ static int mipi_dbi_smartbond_command_read(const struct device *dev, k_sem_take(&data->device_sem, K_FOREVER); + mipi_dbi_smartbond_pm_policy_state_lock_get(); + /* * Add an arbitrary valid color format to satisfy subroutine. The MIPI DBI command/data * engine should not be affected. @@ -283,6 +279,8 @@ _mipi_dbi_read_exit: LOG_ERR("Could not apply MIPI DBI pins' default state (%d)", ret); } + mipi_dbi_smartbond_pm_policy_state_lock_put(); + k_sem_give(&data->device_sem); return ret; @@ -300,7 +298,7 @@ static int mipi_dbi_smartbond_command_write(const struct device *dev, k_sem_take(&data->device_sem, K_FOREVER); - mipi_dbi_pm_get(dev); + mipi_dbi_smartbond_pm_policy_state_lock_get(); /* * Add an arbitrary valid color format to satisfy subroutine. The MIPI DBI command/data @@ -321,7 +319,7 @@ static int mipi_dbi_smartbond_command_write(const struct device *dev, da1469x_lcdc_send_cmd_data(false, data_buf, len); } - mipi_dbi_pm_put(dev); + mipi_dbi_smartbond_pm_policy_state_lock_put(); k_sem_give(&data->device_sem); @@ -349,7 +347,7 @@ static int mipi_dbi_smartbond_write_display(const struct device *dev, k_sem_take(&data->device_sem, K_FOREVER); - mipi_dbi_pm_get(dev); + mipi_dbi_smartbond_pm_policy_state_lock_get(); /* * Mainly check if the frame generator is busy with a pending frame update (might happen @@ -388,7 +386,7 @@ static int mipi_dbi_smartbond_write_display(const struct device *dev, _mipi_dbi_write_exit: - mipi_dbi_pm_put(dev); + mipi_dbi_smartbond_pm_policy_state_lock_put(); k_sem_give(&data->device_sem); @@ -488,33 +486,14 @@ static int mipi_dbi_smartbond_suspend(const struct device *dev) static int mipi_dbi_smartbond_pm_action(const struct device *dev, enum pm_device_action action) { - /* Initialize with an error code that should abort sleeping */ - int ret = -EBUSY; - struct mipi_dbi_smartbond_data *data = dev->data; + int ret = 0; switch (action) { case PM_DEVICE_ACTION_SUSPEND: - /* Sleep is only allowed when there are no active LCDC operations */ - if (!data->is_active) { - (void)mipi_dbi_smartbond_suspend(dev); - /* - * Once the display block is turned off, its power domain - * can be released as well. - */ - da1469x_pd_release_nowait(MCU_PD_DOMAIN_SYS); - ret = 0; - } + /* A non-zero value should not affect sleep */ + (void)mipi_dbi_smartbond_suspend(dev); break; case PM_DEVICE_ACTION_RESUME: - __ASSERT_NO_MSG(!data->is_active); - - /* - * Although PD_SYS should already be turned on, make sure LCD controller's - * power domain is up and running before accessing the display block. - * Acquiring PD_SYS is mandatory when in PM runtime mode. - */ - da1469x_pd_acquire(MCU_PD_DOMAIN_SYS); - /* * The resume error code should not be taken into consideration * by the PM subsystem. @@ -559,7 +538,6 @@ static int mipi_dbi_smartbond_init(const struct device *dev) ret = pm_device_runtime_enable(dev); #else - da1469x_pd_acquire(MCU_PD_DOMAIN_SYS); /* Resme if either PM is not used at all or if PM without runtime is used. */ ret = mipi_dbi_smartbond_resume(dev); #endif