Skip to content

Commit ea23cd1

Browse files
committed
drivers: gpio: silabs-siwx91x: Device runtime PM
This commit enables the pm device runtime support for the siwx91x gpio driver. Signed-off-by: Sai Santhosh Malae <[email protected]>
1 parent 0daacff commit ea23cd1

File tree

1 file changed

+64
-42
lines changed

1 file changed

+64
-42
lines changed

drivers/gpio/gpio_silabs_siwx91x.c

Lines changed: 64 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,17 @@
3131
#define INVALID_PORT 0xFF
3232
#define INTERRUPT_COUNT 8
3333

34+
struct gpio_siwx91x_pin_config_info {
35+
const struct device *port_dev;
36+
gpio_pin_t pin;
37+
gpio_flags_t flags;
38+
};
39+
3440
/* Types */
3541
struct gpio_siwx91x_common_config {
3642
EGPIO_Type *reg;
3743
uint8_t port_count;
44+
uint8_t max_pin_usage_count;
3845
};
3946

4047
struct gpio_siwx91x_port_config {
@@ -51,54 +58,24 @@ struct gpio_siwx91x_common_data {
5158
/* a list of all ports */
5259
const struct device **ports;
5360
sl_gpio_t interrupts[INTERRUPT_COUNT];
61+
struct gpio_siwx91x_pin_config_info *pin_config_info;
62+
uint8_t cur_pin;
5463
};
5564

5665
struct gpio_siwx91x_port_data {
5766
/* gpio_driver_data needs to be first */
5867
struct gpio_driver_data common;
5968
/* port ISR callback routine address */
6069
sys_slist_t callbacks;
61-
#if defined(CONFIG_PM)
62-
/* stores the direction of each pin */
63-
uint16_t pin_direction[MAX_PIN_COUNT];
64-
#endif
6570
};
6671

6772
/* Functions */
68-
static int gpio_siwx91x_port_pm_action(const struct device *port, enum pm_device_action action)
69-
{
70-
__maybe_unused const struct gpio_siwx91x_port_config *config = port->config;
71-
__maybe_unused struct gpio_siwx91x_port_data *data = port->data;
72-
#if defined(CONFIG_PM)
73-
switch (action) {
74-
case PM_DEVICE_ACTION_RESUME:
75-
for (int pin = 0; pin < MAX_PIN_COUNT; ++pin) {
76-
if (config->common.port_pin_mask & BIT(pin)) {
77-
sl_si91x_gpio_set_pin_direction(config->hal_port, pin,
78-
data->pin_direction[pin]);
79-
}
80-
}
81-
break;
82-
case PM_DEVICE_ACTION_SUSPEND:
83-
for (int pin = 0; pin < MAX_PIN_COUNT; ++pin) {
84-
if (config->common.port_pin_mask & BIT(pin)) {
85-
data->pin_direction[pin] =
86-
sl_si91x_gpio_get_pin_direction(config->hal_port, pin);
87-
}
88-
}
89-
break;
90-
default:
91-
return -ENOTSUP;
92-
}
93-
#endif
94-
return 0;
95-
}
96-
9773
static int gpio_siwx91x_pin_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags)
9874
{
9975
const struct gpio_siwx91x_port_config *cfg = dev->config;
10076
const struct device *parent = cfg->parent;
10177
const struct gpio_siwx91x_common_config *pcfg = parent->config;
78+
struct gpio_siwx91x_common_data *pdata = parent->data;
10279
sl_status_t status;
10380
sl_si91x_gpio_driver_disable_state_t disable_state = GPIO_HZ;
10481

@@ -158,6 +135,47 @@ static int gpio_siwx91x_pin_configure(const struct device *dev, gpio_pin_t pin,
158135

159136
sl_si91x_gpio_set_pin_direction(cfg->hal_port, pin, (flags & GPIO_OUTPUT) ? 0 : 1);
160137

138+
if (pdata->cur_pin < pcfg->max_pin_usage_count) {
139+
pdata->pin_config_info[pdata->cur_pin].port_dev = dev;
140+
pdata->pin_config_info[pdata->cur_pin].pin = pin;
141+
pdata->pin_config_info[pdata->cur_pin].flags = flags;
142+
pdata->cur_pin++;
143+
} else {
144+
return -EIO;
145+
}
146+
147+
return 0;
148+
}
149+
150+
static int gpio_siwx91x_pm_action(const struct device *dev, enum pm_device_action action)
151+
{
152+
const struct gpio_siwx91x_common_config *pcfg = dev->config;
153+
struct gpio_siwx91x_common_data *pdata = dev->data;
154+
int ret;
155+
int i = 0;
156+
157+
switch (action) {
158+
case PM_DEVICE_ACTION_TURN_ON:
159+
while (pdata->pin_config_info[i].port_dev != NULL &&
160+
i < pcfg->max_pin_usage_count) {
161+
ret = gpio_siwx91x_pin_configure(pdata->pin_config_info[i].port_dev,
162+
pdata->pin_config_info[i].pin,
163+
pdata->pin_config_info[i].flags);
164+
if (ret) {
165+
return ret;
166+
}
167+
i++;
168+
}
169+
break;
170+
case PM_DEVICE_ACTION_TURN_OFF:
171+
break;
172+
case PM_DEVICE_ACTION_RESUME:
173+
break;
174+
case PM_DEVICE_ACTION_SUSPEND:
175+
break;
176+
default:
177+
return -ENOTSUP;
178+
}
161179
return 0;
162180
}
163181

@@ -331,7 +349,7 @@ static inline int gpio_siwx91x_init_port(const struct device *port)
331349
__ASSERT(cfg->port < pcfg->port_count, "Too many ports");
332350
pdata->ports[cfg->port] = port;
333351

334-
return pm_device_driver_init(port, gpio_siwx91x_port_pm_action);
352+
return 0;
335353
}
336354

337355
static void gpio_siwx91x_isr(const struct device *parent)
@@ -397,10 +415,9 @@ static DEVICE_API(gpio, gpio_siwx91x_api) = {
397415
}; \
398416
static struct gpio_siwx91x_port_data gpio_siwx91x_port_data##n; \
399417
\
400-
PM_DEVICE_DT_INST_DEFINE(n, gpio_siwx91x_port_pm_action); \
401-
DEVICE_DT_DEFINE(n, gpio_siwx91x_init_port, PM_DEVICE_DT_INST_GET(n), \
402-
&gpio_siwx91x_port_data##n, &gpio_siwx91x_port_config##n, PRE_KERNEL_1, \
403-
CONFIG_GPIO_INIT_PRIORITY, &gpio_siwx91x_api);
418+
DEVICE_DT_DEFINE(n, gpio_siwx91x_init_port, NULL, &gpio_siwx91x_port_data##n, \
419+
&gpio_siwx91x_port_config##n, PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, \
420+
&gpio_siwx91x_api);
404421

405422
#define CONFIGURE_SHARED_INTERRUPT(node_id, prop, idx) \
406423
IRQ_CONNECT(DT_IRQ_BY_IDX(node_id, idx, irq), DT_IRQ_BY_IDX(node_id, idx, priority), \
@@ -411,12 +428,16 @@ static DEVICE_API(gpio, gpio_siwx91x_common_api) = { };
411428

412429
#define GPIO_CONTROLLER_INIT(idx) \
413430
const struct device *ports_##idx[DT_INST_PROP(idx, silabs_port_count)]; \
431+
struct gpio_siwx91x_pin_config_info \
432+
pin_config_info_##idx[DT_INST_PROP(idx, silabs_max_pin_usage_count)]; \
414433
static const struct gpio_siwx91x_common_config gpio_siwx91x_config##idx = { \
415434
.reg = (EGPIO_Type *)DT_INST_REG_ADDR(idx), \
416435
.port_count = DT_INST_PROP(idx, silabs_port_count), \
436+
.max_pin_usage_count = DT_INST_PROP(idx, silabs_max_pin_usage_count), \
417437
}; \
418438
static struct gpio_siwx91x_common_data gpio_siwx91x_data##idx = { \
419439
.ports = ports_##idx, \
440+
.pin_config_info = pin_config_info_##idx, \
420441
}; \
421442
\
422443
static int gpio_siwx91x_init_controller_##idx(const struct device *dev) \
@@ -433,11 +454,12 @@ static DEVICE_API(gpio, gpio_siwx91x_common_api) = { };
433454
data->interrupts[i].port = INVALID_PORT; \
434455
} \
435456
DT_INST_FOREACH_PROP_ELEM(idx, interrupt_names, CONFIGURE_SHARED_INTERRUPT); \
436-
return 0; \
457+
return pm_device_driver_init(dev, gpio_siwx91x_pm_action); \
437458
} \
438-
DEVICE_DT_INST_DEFINE(idx, gpio_siwx91x_init_controller_##idx, NULL, \
439-
&gpio_siwx91x_data##idx, &gpio_siwx91x_config##idx, \
440-
PRE_KERNEL_1, CONFIG_GPIO_SILABS_SIWX91X_COMMON_INIT_PRIORITY, \
459+
PM_DEVICE_DT_INST_DEFINE(idx, gpio_siwx91x_pm_action); \
460+
DEVICE_DT_INST_DEFINE(idx, gpio_siwx91x_init_controller_##idx, PM_DEVICE_DT_INST_GET(idx), \
461+
&gpio_siwx91x_data##idx, &gpio_siwx91x_config##idx, PRE_KERNEL_1, \
462+
CONFIG_GPIO_SILABS_SIWX91X_COMMON_INIT_PRIORITY, \
441463
&gpio_siwx91x_common_api); \
442464
DT_INST_FOREACH_CHILD_STATUS_OKAY(idx, GPIO_PORT_INIT);
443465

0 commit comments

Comments
 (0)