31
31
#define INVALID_PORT 0xFF
32
32
#define INTERRUPT_COUNT 8
33
33
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
+
34
40
/* Types */
35
41
struct gpio_siwx91x_common_config {
36
42
EGPIO_Type * reg ;
@@ -58,48 +64,20 @@ struct gpio_siwx91x_port_data {
58
64
struct gpio_driver_data common ;
59
65
/* port ISR callback routine address */
60
66
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
67
+ struct gpio_siwx91x_pin_config_info * pin_config_info ;
68
+ uint8_t next_pin ;
65
69
};
66
70
67
71
/* 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
-
97
72
static int gpio_siwx91x_pin_configure (const struct device * dev , gpio_pin_t pin , gpio_flags_t flags )
98
73
{
99
74
const struct gpio_siwx91x_port_config * cfg = dev -> config ;
75
+ struct gpio_siwx91x_port_data * port_data = dev -> data ;
100
76
const struct device * parent = cfg -> parent ;
101
77
const struct gpio_siwx91x_common_config * pcfg = parent -> config ;
78
+ uint8_t cur_cfg_pin = 0 ;
102
79
sl_status_t status ;
80
+ int i ;
103
81
sl_si91x_gpio_driver_disable_state_t disable_state = GPIO_HZ ;
104
82
105
83
if (flags & GPIO_SINGLE_ENDED ) {
@@ -158,6 +136,67 @@ static int gpio_siwx91x_pin_configure(const struct device *dev, gpio_pin_t pin,
158
136
159
137
sl_si91x_gpio_set_pin_direction (cfg -> hal_port , pin , (flags & GPIO_OUTPUT ) ? 0 : 1 );
160
138
139
+ for (i = 0 ; i < port_data -> next_pin ; i ++ ) {
140
+ if (port_data -> pin_config_info [i ].pin == pin ) {
141
+ cur_cfg_pin = i ;
142
+ break ;
143
+ }
144
+ }
145
+
146
+ if (i == port_data -> next_pin ) {
147
+ cur_cfg_pin = port_data -> next_pin ;
148
+ port_data -> next_pin ++ ;
149
+ }
150
+
151
+ if (cur_cfg_pin < __builtin_popcount (cfg -> common .port_pin_mask )) {
152
+ port_data -> pin_config_info [cur_cfg_pin ].port_dev = dev ;
153
+ port_data -> pin_config_info [cur_cfg_pin ].pin = pin ;
154
+ port_data -> pin_config_info [cur_cfg_pin ].flags = flags ;
155
+ } else {
156
+ return - EIO ;
157
+ }
158
+
159
+ return 0 ;
160
+ }
161
+
162
+ static int gpio_siwx91x_pm_action (const struct device * dev , enum pm_device_action action )
163
+ {
164
+ const struct gpio_siwx91x_common_config * cfg = dev -> config ;
165
+ struct gpio_siwx91x_common_data * data = dev -> data ;
166
+ const struct device * * port_dev = data -> ports ;
167
+ const struct gpio_siwx91x_port_config * port_cfg = NULL ;
168
+ struct gpio_siwx91x_port_data * port_data = NULL ;
169
+ int pin_cnt ;
170
+ int ret ;
171
+
172
+ switch (action ) {
173
+ case PM_DEVICE_ACTION_TURN_ON :
174
+ for (int i = 0 ; i < cfg -> port_count ; i ++ ) {
175
+ port_cfg = port_dev [i ]-> config ;
176
+ port_data = port_dev [i ]-> data ;
177
+ pin_cnt = 0 ;
178
+ while (port_data -> pin_config_info [pin_cnt ].port_dev != NULL &&
179
+ pin_cnt < __builtin_popcount (port_cfg -> common .port_pin_mask )) {
180
+ ret = gpio_siwx91x_pin_configure (
181
+ port_data -> pin_config_info [pin_cnt ].port_dev ,
182
+ port_data -> pin_config_info [pin_cnt ].pin ,
183
+ port_data -> pin_config_info [pin_cnt ].flags );
184
+ if (ret ) {
185
+ return ret ;
186
+ }
187
+ pin_cnt ++ ;
188
+ }
189
+ }
190
+ break ;
191
+ case PM_DEVICE_ACTION_TURN_OFF :
192
+ break ;
193
+ case PM_DEVICE_ACTION_RESUME :
194
+ break ;
195
+ case PM_DEVICE_ACTION_SUSPEND :
196
+ break ;
197
+ default :
198
+ return - ENOTSUP ;
199
+ }
161
200
return 0 ;
162
201
}
163
202
@@ -322,16 +361,16 @@ static int gpio_siwx91x_interrupt_configure(const struct device *port, gpio_pin_
322
361
323
362
static inline int gpio_siwx91x_init_port (const struct device * port )
324
363
{
325
- const struct gpio_siwx91x_port_config * cfg = port -> config ;
326
- const struct device * parent = cfg -> parent ;
327
- __maybe_unused const struct gpio_siwx91x_common_config * pcfg = parent -> config ;
328
- struct gpio_siwx91x_common_data * pdata = parent -> data ;
364
+ const struct gpio_siwx91x_port_config * port_cfg = port -> config ;
365
+ const struct device * parent = port_cfg -> parent ;
366
+ __maybe_unused const struct gpio_siwx91x_common_config * cfg = parent -> config ;
367
+ struct gpio_siwx91x_common_data * data = parent -> data ;
329
368
330
369
/* Register port as active */
331
- __ASSERT (cfg -> port < pcfg -> port_count , "Too many ports" );
332
- pdata -> ports [cfg -> port ] = port ;
370
+ __ASSERT (port_cfg -> port < cfg -> port_count , "Too many ports" );
371
+ data -> ports [port_cfg -> port ] = port ;
333
372
334
- return pm_device_driver_init ( port , gpio_siwx91x_port_pm_action ) ;
373
+ return 0 ;
335
374
}
336
375
337
376
static void gpio_siwx91x_isr (const struct device * parent )
@@ -386,6 +425,8 @@ static DEVICE_API(gpio, gpio_siwx91x_api) = {
386
425
};
387
426
388
427
#define GPIO_PORT_INIT (n ) \
428
+ struct gpio_siwx91x_pin_config_info \
429
+ pin_config_info_##n[__builtin_popcount(GPIO_PORT_PIN_MASK_FROM_DT_NODE(n))]; \
389
430
static const struct gpio_siwx91x_port_config gpio_siwx91x_port_config##n = { \
390
431
.common.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_NODE(n), \
391
432
.parent = DEVICE_DT_GET(DT_PARENT(n)), \
@@ -395,12 +436,13 @@ static DEVICE_API(gpio, gpio_siwx91x_api) = {
395
436
DT_REG_ADDR(n), \
396
437
.ulp = DT_PROP(DT_PARENT(n), silabs_ulp), \
397
438
}; \
398
- static struct gpio_siwx91x_port_data gpio_siwx91x_port_data##n; \
439
+ static struct gpio_siwx91x_port_data gpio_siwx91x_port_data##n = { \
440
+ .pin_config_info = pin_config_info_##n, \
441
+ }; \
399
442
\
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);
443
+ DEVICE_DT_DEFINE(n, gpio_siwx91x_init_port, NULL, &gpio_siwx91x_port_data##n, \
444
+ &gpio_siwx91x_port_config##n, PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, \
445
+ &gpio_siwx91x_api);
404
446
405
447
#define CONFIGURE_SHARED_INTERRUPT (node_id , prop , idx ) \
406
448
IRQ_CONNECT(DT_IRQ_BY_IDX(node_id, idx, irq), DT_IRQ_BY_IDX(node_id, idx, priority), \
@@ -433,11 +475,12 @@ static DEVICE_API(gpio, gpio_siwx91x_common_api) = { };
433
475
data->interrupts[i].port = INVALID_PORT; \
434
476
} \
435
477
DT_INST_FOREACH_PROP_ELEM(idx, interrupt_names, CONFIGURE_SHARED_INTERRUPT); \
436
- return 0; \
478
+ return pm_device_driver_init(dev, gpio_siwx91x_pm_action); \
437
479
} \
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, \
480
+ PM_DEVICE_DT_INST_DEFINE(idx, gpio_siwx91x_pm_action); \
481
+ DEVICE_DT_INST_DEFINE(idx, gpio_siwx91x_init_controller_##idx, PM_DEVICE_DT_INST_GET(idx), \
482
+ &gpio_siwx91x_data##idx, &gpio_siwx91x_config##idx, PRE_KERNEL_1, \
483
+ CONFIG_GPIO_SILABS_SIWX91X_COMMON_INIT_PRIORITY, \
441
484
&gpio_siwx91x_common_api); \
442
485
DT_INST_FOREACH_CHILD_STATUS_OKAY(idx, GPIO_PORT_INIT);
443
486
0 commit comments