2222#include <drivers/pinmux.h>
2323#include <sys/util.h>
2424#include <drivers/interrupt_controller/exti_stm32.h>
25+ #include <pm/device.h>
26+ #include <pm/device_runtime.h>
2527
2628#include "stm32_hsem.h"
2729#include "gpio_stm32.h"
@@ -238,7 +240,6 @@ int gpio_stm32_clock_request(const struct device *dev, bool on)
238240 if (on ) {
239241 ret = clock_control_on (clk ,
240242 (clock_control_subsys_t * )& cfg -> pclken );
241-
242243 } else {
243244 ret = clock_control_off (clk ,
244245 (clock_control_subsys_t * )& cfg -> pclken );
@@ -463,6 +464,9 @@ static int gpio_stm32_port_toggle_bits(const struct device *dev,
463464static int gpio_stm32_config (const struct device * dev ,
464465 gpio_pin_t pin , gpio_flags_t flags )
465466{
467+ #ifdef CONFIG_PM_DEVICE_RUNTIME
468+ struct gpio_stm32_data * data = dev -> data ;
469+ #endif /* CONFIG_PM_DEVICE_RUNTIME */
466470 int err = 0 ;
467471 int pincfg ;
468472
@@ -474,6 +478,16 @@ static int gpio_stm32_config(const struct device *dev,
474478 goto exit ;
475479 }
476480
481+ #ifdef CONFIG_PM_DEVICE_RUNTIME
482+ /* Enable device clock before configuration (requires bank writes) */
483+ if (data -> power_state != PM_DEVICE_ACTIVE_STATE ) {
484+ err = pm_device_get_sync (dev );
485+ if (err < 0 ) {
486+ return err ;
487+ }
488+ }
489+ #endif /* CONFIG_PM_DEVICE_RUNTIME */
490+
477491 if ((flags & GPIO_OUTPUT ) != 0 ) {
478492 if ((flags & GPIO_OUTPUT_INIT_HIGH ) != 0 ) {
479493 gpio_stm32_port_set_bits_raw (dev , BIT (pin ));
@@ -484,6 +498,17 @@ static int gpio_stm32_config(const struct device *dev,
484498
485499 gpio_stm32_configure (dev , pin , pincfg , 0 );
486500
501+ /* Device released */
502+ #ifdef CONFIG_PM_DEVICE_RUNTIME
503+ /* Release clock only if configuration doesn't require bank writes */
504+ if ((flags & GPIO_OUTPUT ) == 0 ) {
505+ err = pm_device_put (dev );
506+ if (err < 0 ) {
507+ return err ;
508+ }
509+ }
510+ #endif /* CONFIG_PM_DEVICE_RUNTIME */
511+
487512exit :
488513 return err ;
489514}
@@ -561,6 +586,69 @@ static const struct gpio_driver_api gpio_stm32_driver = {
561586 .manage_callback = gpio_stm32_manage_callback ,
562587};
563588
589+ #ifdef CONFIG_PM_DEVICE
590+ static uint32_t gpio_stm32_get_power_state (const struct device * dev )
591+ {
592+ struct gpio_stm32_data * data = dev -> data ;
593+
594+ return data -> power_state ;
595+ }
596+
597+ static int gpio_stm32_set_power_state (const struct device * dev ,
598+ uint32_t new_state )
599+ {
600+ struct gpio_stm32_data * data = dev -> data ;
601+ int ret = 0 ;
602+
603+ if (new_state == PM_DEVICE_ACTIVE_STATE ) {
604+ ret = gpio_stm32_clock_request (dev , true);
605+ } else if (new_state == PM_DEVICE_SUSPEND_STATE ) {
606+ ret = gpio_stm32_clock_request (dev , false);
607+ } else if (new_state == PM_DEVICE_LOW_POWER_STATE ) {
608+ ret = gpio_stm32_clock_request (dev , false);
609+ }
610+
611+ if (ret < 0 ) {
612+ return ret ;
613+ }
614+
615+ data -> power_state = new_state ;
616+
617+ return 0 ;
618+ }
619+
620+ static int gpio_stm32_pm_device_ctrl (const struct device * dev ,
621+ uint32_t ctrl_command ,
622+ void * context , pm_device_cb cb , void * arg )
623+ {
624+ struct gpio_stm32_data * data = dev -> data ;
625+ uint32_t new_state ;
626+ int ret = 0 ;
627+
628+ switch (ctrl_command ) {
629+ case PM_DEVICE_STATE_SET :
630+ new_state = * ((const uint32_t * )context );
631+ if (new_state != data -> power_state ) {
632+ ret = gpio_stm32_set_power_state (dev , new_state );
633+ }
634+ break ;
635+ case PM_DEVICE_STATE_GET :
636+ * ((uint32_t * )context ) = gpio_stm32_get_power_state (dev );
637+ break ;
638+ default :
639+ ret = - EINVAL ;
640+
641+ }
642+
643+ if (cb ) {
644+ cb (dev , ret , context , arg );
645+ }
646+
647+ return ret ;
648+ }
649+ #endif /* CONFIG_PM_DEVICE */
650+
651+
564652/**
565653 * @brief Initialize GPIO port
566654 *
@@ -577,7 +665,25 @@ static int gpio_stm32_init(const struct device *dev)
577665
578666 data -> dev = dev ;
579667
668+ #if defined(PWR_CR2_IOSV ) && DT_NODE_HAS_STATUS (DT_NODELABEL (gpiog ), okay )
669+ z_stm32_hsem_lock (CFG_HW_RCC_SEMID , HSEM_LOCK_DEFAULT_RETRY );
670+ /* Port G[15:2] requires external power supply */
671+ /* Cf: L4/L5 RM, Chapter "Independent I/O supply rail" */
672+ LL_PWR_EnableVddIO2 ();
673+ z_stm32_hsem_unlock (CFG_HW_RCC_SEMID );
674+ #endif
675+
676+ #ifdef CONFIG_PM_DEVICE_RUNTIME
677+ data -> power_state = PM_DEVICE_OFF_STATE ;
678+ pm_device_enable (dev );
679+
680+ return 0 ;
681+ #else
682+ #ifdef CONFIG_PM_DEVICE
683+ data -> power_state = PM_DEVICE_ACTIVE_STATE ;
684+ #endif
580685 return gpio_stm32_clock_request (dev , true);
686+ #endif
581687}
582688
583689#define GPIO_DEVICE_INIT (__node , __suffix , __base_addr , __port , __cenr , __bus ) \
@@ -592,7 +698,7 @@ static int gpio_stm32_init(const struct device *dev)
592698 static struct gpio_stm32_data gpio_stm32_data_## __suffix; \
593699 DEVICE_DT_DEFINE(__node, \
594700 gpio_stm32_init, \
595- NULL, \
701+ gpio_stm32_pm_device_ctrl, \
596702 &gpio_stm32_data_## __suffix, \
597703 &gpio_stm32_cfg_## __suffix, \
598704 POST_KERNEL, \
0 commit comments