diff --git a/drivers/gpio/Kconfig.smartbond b/drivers/gpio/Kconfig.smartbond index 5e624cd301..59c8b2f109 100644 --- a/drivers/gpio/Kconfig.smartbond +++ b/drivers/gpio/Kconfig.smartbond @@ -5,5 +5,6 @@ config GPIO_SMARTBOND bool "Renesas SmartBond(tm) GPIO driver" default y depends on DT_HAS_RENESAS_SMARTBOND_GPIO_ENABLED + select PM_DEVICE if PM help Enable GPIO driver for Renesas SmartBond(tm) MCU family. diff --git a/drivers/gpio/gpio_smartbond.c b/drivers/gpio/gpio_smartbond.c index 81ce31296f..06af6ffb62 100644 --- a/drivers/gpio/gpio_smartbond.c +++ b/drivers/gpio/gpio_smartbond.c @@ -11,9 +11,11 @@ #include #include #include +#include #include #include +#include #define GPIO_MODE_RESET 0x200 @@ -60,6 +62,14 @@ struct gpio_smartbond_data { /* Pins that are configured for both edges (handled by software) */ gpio_port_pins_t both_edges_pins; sys_slist_t callbacks; +#if CONFIG_PM_DEVICE + /* + * Saved state consist of: + * 1 word for GPIO output port state + * GPIOx_NGPIOS words for each pin mode + */ + uint32_t *gpio_saved_state; +#endif }; struct gpio_smartbond_config { @@ -71,6 +81,9 @@ struct gpio_smartbond_config { volatile struct gpio_smartbond_wkup_regs *wkup_regs; /* Value of TRIG_SELECT for PDC_CTRLx_REG entry */ uint8_t wkup_trig_select; +#if CONFIG_PM_DEVICE + uint8_t ngpios; +#endif }; static void gpio_smartbond_wkup_init(void) @@ -292,6 +305,78 @@ static void gpio_smartbond_isr(const struct device *dev) gpio_fire_callbacks(&data->callbacks, dev, stat); } +#ifdef CONFIG_PM_DEVICE + +static void gpio_latch_inst(mem_addr_t data_reg, mem_addr_t mode_reg, mem_addr_t latch_reg, + uint8_t ngpios, uint32_t *data, uint32_t *mode) +{ + uint8_t idx; + + *data = sys_read32(data_reg); + for (idx = 0; idx < ngpios; idx++, mode_reg += 4) { + mode[idx] = sys_read32(mode_reg); + } + sys_write32(BIT_MASK(ngpios), latch_reg); + +} + +static void gpio_unlatch_inst(mem_addr_t data_reg, mem_addr_t mode_reg, mem_addr_t latch_reg, + uint8_t ngpios, uint32_t data, uint32_t *mode) +{ + uint8_t idx; + + sys_write32(data, data_reg); + for (idx = 0; idx < ngpios; idx++, mode_reg += 4) { + sys_write32(mode[idx], mode_reg); + } + sys_write32(BIT_MASK(ngpios), latch_reg); +} + +static void gpio_latch(const struct device *dev) +{ + const struct gpio_smartbond_config *config = dev->config; + const struct gpio_smartbond_data *data = dev->data; + + gpio_latch_inst((mem_addr_t)&config->data_regs->data, + (mem_addr_t)config->mode_regs, + (mem_addr_t)&config->latch_regs->reset, + config->ngpios, data->gpio_saved_state, data->gpio_saved_state + 1); +} + +static void gpio_unlatch(const struct device *dev) +{ + const struct gpio_smartbond_config *config = dev->config; + const struct gpio_smartbond_data *data = dev->data; + + gpio_unlatch_inst((mem_addr_t)&config->data_regs->data, + (mem_addr_t)config->mode_regs, + (mem_addr_t)&config->latch_regs->set, + config->ngpios, data->gpio_saved_state[0], data->gpio_saved_state + 1); +} + +static int gpio_smartbond_pm_action(const struct device *dev, + enum pm_device_action action) +{ + int ret = 0; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + da1469x_pd_acquire(MCU_PD_DOMAIN_COM); + gpio_unlatch(dev); + break; + case PM_DEVICE_ACTION_SUSPEND: + gpio_latch(dev); + da1469x_pd_release(MCU_PD_DOMAIN_COM); + break; + default: + ret = -ENOTSUP; + } + + return ret; +} + +#endif /* CONFIG_PM_DEVICE */ + /* GPIO driver registration */ static const struct gpio_driver_api gpio_smartbond_drv_api_funcs = { .pin_configure = gpio_smartbond_pin_configure, @@ -304,8 +389,15 @@ static const struct gpio_driver_api gpio_smartbond_drv_api_funcs = { .manage_callback = gpio_smartbond_manage_callback, }; +#define GPIO_SAVED_STATE(id) gpio_smartbond_saved_state_##id +#define GPIO_PM_DEVICE_CFG(fld, val) \ + COND_CODE_1(CONFIG_PM_DEVICE, (fld = val,), ()) +#define GPIO_PM_DEVICE_STATE(id, ngpios) \ + COND_CODE_1(CONFIG_PM_DEVICE, (static uint32_t GPIO_SAVED_STATE(id)[1 + ngpios];), ()) + #define GPIO_SMARTBOND_DEVICE(id) \ - static const struct gpio_smartbond_config gpio_smartbond_p##id##_config = { \ + GPIO_PM_DEVICE_STATE(id, DT_INST_PROP(id, ngpios)) \ + static const struct gpio_smartbond_config gpio_smartbond_config_##id = { \ .common = { \ .port_pin_mask = \ GPIO_PORT_PIN_MASK_FROM_DT_INST(id), \ @@ -318,12 +410,16 @@ static const struct gpio_driver_api gpio_smartbond_drv_api_funcs = { .wkup_regs = (volatile struct gpio_smartbond_wkup_regs *) \ DT_INST_REG_ADDR_BY_NAME(id, wkup), \ .wkup_trig_select = id, \ + GPIO_PM_DEVICE_CFG(.ngpios, DT_INST_PROP(id, ngpios)) \ }; \ \ - static struct gpio_smartbond_data gpio_smartbond_p##id##_data; \ + static struct gpio_smartbond_data gpio_smartbond_data_##id = { \ + GPIO_PM_DEVICE_CFG(.gpio_saved_state, GPIO_SAVED_STATE(id)) \ + }; \ \ - static int gpio_smartbond_##id##_init(const struct device *dev) \ + static int gpio_smartbond_init_##id(const struct device *dev) \ { \ + da1469x_pd_acquire(MCU_PD_DOMAIN_COM); \ gpio_smartbond_wkup_init(); \ IRQ_CONNECT(DT_INST_IRQN(id), \ DT_INST_IRQ(id, priority), \ @@ -333,10 +429,11 @@ static const struct gpio_driver_api gpio_smartbond_drv_api_funcs = { return 0; \ } \ \ - DEVICE_DT_INST_DEFINE(id, gpio_smartbond_##id##_init, \ - NULL, \ - &gpio_smartbond_p##id##_data, \ - &gpio_smartbond_p##id##_config, \ + PM_DEVICE_DEFINE(id, gpio_smartbond_pm_action); \ + DEVICE_DT_INST_DEFINE(id, gpio_smartbond_init_##id, \ + PM_DEVICE_GET(id), \ + &gpio_smartbond_data_##id, \ + &gpio_smartbond_config_##id, \ PRE_KERNEL_1, \ CONFIG_GPIO_INIT_PRIORITY, \ &gpio_smartbond_drv_api_funcs); diff --git a/soc/renesas/smartbond/da1469x/soc.c b/soc/renesas/smartbond/da1469x/soc.c index 8d6a23a2d9..28a21d3aa8 100644 --- a/soc/renesas/smartbond/da1469x/soc.c +++ b/soc/renesas/smartbond/da1469x/soc.c @@ -175,7 +175,6 @@ static int renesas_da1469x_init(void) da1469x_pd_init(); da1469x_pd_acquire(MCU_PD_DOMAIN_SYS); da1469x_pd_acquire(MCU_PD_DOMAIN_TIM); - da1469x_pd_acquire(MCU_PD_DOMAIN_COM); return 0; }