diff --git a/boards/arduino/nano_matter/arduino_nano_matter.dts b/boards/arduino/nano_matter/arduino_nano_matter.dts index ee4a90e9ffb1..53bdc166f63b 100644 --- a/boards/arduino/nano_matter/arduino_nano_matter.dts +++ b/boards/arduino/nano_matter/arduino_nano_matter.dts @@ -176,7 +176,6 @@ }; &gpio { - location-swo = <0>; status = "okay"; }; diff --git a/boards/seeed/xiao_mg24/xiao_mg24.dts b/boards/seeed/xiao_mg24/xiao_mg24.dts index f802fe590fc2..c0235a95ded1 100644 --- a/boards/seeed/xiao_mg24/xiao_mg24.dts +++ b/boards/seeed/xiao_mg24/xiao_mg24.dts @@ -141,7 +141,6 @@ }; &gpio { - location-swo = <0>; status = "okay"; }; diff --git a/boards/silabs/dev_kits/sltb010a/thunderboard.dtsi b/boards/silabs/dev_kits/sltb010a/thunderboard.dtsi index ce4d70224c37..6f8851451e35 100644 --- a/boards/silabs/dev_kits/sltb010a/thunderboard.dtsi +++ b/boards/silabs/dev_kits/sltb010a/thunderboard.dtsi @@ -119,7 +119,6 @@ }; &gpio { - location-swo = <0>; status = "okay"; }; diff --git a/boards/silabs/dev_kits/xg27_dk2602a/thunderboard.dtsi b/boards/silabs/dev_kits/xg27_dk2602a/thunderboard.dtsi index b1b54af5ab34..c571e4744c97 100644 --- a/boards/silabs/dev_kits/xg27_dk2602a/thunderboard.dtsi +++ b/boards/silabs/dev_kits/xg27_dk2602a/thunderboard.dtsi @@ -119,7 +119,6 @@ }; &gpio { - location-swo = <0>; status = "okay"; }; diff --git a/boards/silabs/radio_boards/xg24_rb4187c/xg24_rb4187c.dts b/boards/silabs/radio_boards/xg24_rb4187c/xg24_rb4187c.dts index 1f7fe9222e38..eadc87760f41 100644 --- a/boards/silabs/radio_boards/xg24_rb4187c/xg24_rb4187c.dts +++ b/boards/silabs/radio_boards/xg24_rb4187c/xg24_rb4187c.dts @@ -183,7 +183,6 @@ }; &gpio { - location-swo = <0>; status = "okay"; }; diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index 565591cd0955..0e1cf4155ed9 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -102,6 +102,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_SAM_PIO4 gpio_sam_pio4.c) zephyr_library_sources_ifdef(CONFIG_GPIO_SEDI gpio_sedi.c) zephyr_library_sources_ifdef(CONFIG_GPIO_SI32 gpio_si32.c) zephyr_library_sources_ifdef(CONFIG_GPIO_SIFIVE gpio_sifive.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_SILABS gpio_silabs.c) zephyr_library_sources_ifdef(CONFIG_GPIO_SILABS_SIWX91X gpio_silabs_siwx91x.c) zephyr_library_sources_ifdef(CONFIG_GPIO_SILABS_SIWX91X_UULP gpio_silabs_siwx91x_uulp.c) zephyr_library_sources_ifdef(CONFIG_GPIO_SMARTBOND gpio_smartbond.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 72e8bab03808..87271f0ff941 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -185,6 +185,7 @@ source "drivers/gpio/Kconfig.sc18im704" source "drivers/gpio/Kconfig.sedi" source "drivers/gpio/Kconfig.si32" source "drivers/gpio/Kconfig.sifive" +source "drivers/gpio/Kconfig.silabs" source "drivers/gpio/Kconfig.siwx91x" source "drivers/gpio/Kconfig.smartbond" source "drivers/gpio/Kconfig.sn74hc595" diff --git a/drivers/gpio/Kconfig.silabs b/drivers/gpio/Kconfig.silabs new file mode 100644 index 000000000000..4f21aeb25dc1 --- /dev/null +++ b/drivers/gpio/Kconfig.silabs @@ -0,0 +1,19 @@ +# Copyright (c) 2025 Silicon Laboratories Inc. +# SPDX-License-Identifier: Apache-2.0 + +menuconfig GPIO_SILABS + bool "Silabs GPIO driver" + default y + depends on DT_HAS_SILABS_GPIO_ENABLED + select SILABS_SISDK_GPIO + help + Enable the Silabs gpio driver. + +if GPIO_SILABS + +config GPIO_SILABS_COMMON_INIT_PRIORITY + int "Common initialization priority" + depends on GPIO_SILABS + default 39 + +endif # GPIO_SILABS diff --git a/drivers/gpio/gpio_silabs.c b/drivers/gpio/gpio_silabs.c new file mode 100644 index 000000000000..aa37cb22f1f6 --- /dev/null +++ b/drivers/gpio/gpio_silabs.c @@ -0,0 +1,415 @@ +/* + * Copyright (c) 2025 Silicon Laboratories Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT silabs_gpio + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(gpio_silabs, CONFIG_GPIO_LOG_LEVEL); + +#if GPIO_SILABS_COMMON_INIT_PRIORITY >= CONFIG_GPIO_INIT_PRIORITY +#error GPIO_SILABS_COMMON_INIT_PRIORITY must be less than CONFIG_GPIO_INIT_PRIORITY +#endif + +#define SILABS_GPIO_PORT_ADDR_SPACE_SIZE sizeof(GPIO_PORT_TypeDef) +#define GET_SILABS_GPIO_INDEX(node_id) \ + (DT_REG_ADDR(node_id) - DT_REG_ADDR(DT_NODELABEL(gpioa))) / SILABS_GPIO_PORT_ADDR_SPACE_SIZE + +#define NUMBER_OF_PORTS (SIZEOF_FIELD(GPIO_TypeDef, P) / SIZEOF_FIELD(GPIO_TypeDef, P[0])) + +struct gpio_silabs_common_config { + /* IRQ configuration function */ + void (*irq_connect)(const struct device *dev); + /* Clock device */ + const struct device *clock; + /* Clock control subsystem */ + const struct silabs_clock_control_cmu_config clock_cfg; +}; + +struct gpio_silabs_common_data { + /* a list of all registered GPIO port devices */ + const struct device *ports[NUMBER_OF_PORTS]; + /* Total number of registered ports */ + size_t count; + /* maps interrupt line index to GPIO pin number, 0xFF if unused */ + uint8_t irq_pin_map[16]; +}; + +struct gpio_silabs_port_config { + /* gpio_driver_config must be first */ + struct gpio_driver_config common; + /* index of the GPIO port */ + sl_gpio_port_t gpio_index; +}; + +struct gpio_silabs_port_data { + /* gpio_driver_data must be first */ + struct gpio_driver_data common; + /* port ISR callback routine list */ + sys_slist_t callbacks; + /* bitmask of pins with interrupt enabled */ + uint32_t int_enabled_mask; + /* pointer to common device */ + const struct device *common_dev; +}; + +static inline void gpio_silabs_add_port(struct gpio_silabs_common_data *data, + const struct device *dev) +{ + __ASSERT(dev, "No port device!"); + data->ports[data->count++] = dev; + LOG_DBG("Added GPIO port %s, count: %d", dev->name, data->count); +} + +static int gpio_silabs_pin_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) +{ + const struct gpio_silabs_port_config *config = dev->config; + sl_gpio_t gpio = {.port = config->gpio_index, .pin = pin}; + sl_gpio_mode_t mode; + uint16_t out = 0U; + bool pin_out; + + if (flags & GPIO_OUTPUT) { + if (flags & GPIO_SINGLE_ENDED) { + if (flags & GPIO_LINE_OPEN_DRAIN) { + mode = SL_GPIO_MODE_WIRED_AND; + } else { + mode = SL_GPIO_MODE_WIRED_OR; + } + } else { + mode = SL_GPIO_MODE_PUSH_PULL; + } + if (flags & GPIO_OUTPUT_INIT_HIGH) { + out = 1U; + } else if (flags & GPIO_OUTPUT_INIT_LOW) { + out = 0U; + } else { + pin_out = sl_hal_gpio_get_pin_output(&gpio); + out = pin_out; + } + } else if (flags & GPIO_INPUT) { + if (flags & GPIO_PULL_UP) { + mode = SL_GPIO_MODE_INPUT_PULL; + out = 1U; + } else if (flags & GPIO_PULL_DOWN) { + mode = SL_GPIO_MODE_INPUT_PULL; + } else { + mode = SL_GPIO_MODE_INPUT; + } + } else { + mode = SL_GPIO_MODE_DISABLED; + } + + sl_hal_gpio_set_pin_mode(&gpio, mode, out); + return 0; +} + +#ifdef CONFIG_GPIO_GET_CONFIG +static int gpio_silabs_pin_get_config(const struct device *dev, gpio_pin_t pin, + gpio_flags_t *out_flags) +{ + const struct gpio_silabs_port_config *config = dev->config; + sl_gpio_t gpio = {.port = config->gpio_index, .pin = pin}; + sl_gpio_mode_t mode; + bool out; + gpio_flags_t flags = 0; + + mode = sl_hal_gpio_get_pin_mode(&gpio); + out = sl_hal_gpio_get_pin_output(&gpio); + + switch (mode) { + case SL_GPIO_MODE_WIRED_AND: + flags = GPIO_OUTPUT | GPIO_OPEN_DRAIN; + + if (out) { + flags |= GPIO_OUTPUT_HIGH; + } else { + flags |= GPIO_OUTPUT_LOW; + } + break; + + case SL_GPIO_MODE_WIRED_OR: + flags = GPIO_OUTPUT | GPIO_OPEN_SOURCE; + + if (out) { + flags |= GPIO_OUTPUT_HIGH; + } else { + flags |= GPIO_OUTPUT_LOW; + } + break; + + case SL_GPIO_MODE_PUSH_PULL: + flags = GPIO_OUTPUT | GPIO_PUSH_PULL; + + if (out) { + flags |= GPIO_OUTPUT_HIGH; + } else { + flags |= GPIO_OUTPUT_LOW; + } + break; + + case SL_GPIO_MODE_INPUT_PULL: + flags = GPIO_INPUT; + + if (out) { + flags |= GPIO_PULL_UP; + } else { + flags |= GPIO_PULL_DOWN; + } + break; + + case SL_GPIO_MODE_INPUT: + flags = GPIO_INPUT; + break; + + case SL_GPIO_MODE_DISABLED: + flags = GPIO_DISCONNECTED; + break; + + default: + break; + } + + *out_flags = flags; + return 0; +} +#endif + +static int gpio_silabs_port_get_raw(const struct device *dev, gpio_port_value_t *value) +{ + const struct gpio_silabs_port_config *config = dev->config; + + *value = sl_hal_gpio_get_port_input(config->gpio_index); + + return 0; +} + +static int gpio_silabs_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask, + gpio_port_value_t value) +{ + const struct gpio_silabs_port_config *config = dev->config; + + sl_hal_gpio_set_port_value(config->gpio_index, value, mask); + + return 0; +} + +static int gpio_silabs_port_set_bits_raw(const struct device *dev, gpio_port_pins_t mask) +{ + const struct gpio_silabs_port_config *config = dev->config; + + sl_hal_gpio_set_port(config->gpio_index, mask); + + return 0; +} + +static int gpio_silabs_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t mask) +{ + const struct gpio_silabs_port_config *config = dev->config; + + sl_hal_gpio_clear_port(config->gpio_index, mask); + + return 0; +} + +static int gpio_silabs_port_toggle_bits(const struct device *dev, gpio_port_pins_t mask) +{ + const struct gpio_silabs_port_config *config = dev->config; + + sl_hal_gpio_toggle_port(config->gpio_index, mask); + + return 0; +} + +static int gpio_silabs_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, + enum gpio_int_mode mode, enum gpio_int_trig trig) +{ + const struct gpio_silabs_port_config *config = dev->config; + struct gpio_silabs_port_data *data = dev->data; + struct gpio_silabs_common_data *common = data->common_dev->data; + sl_gpio_t gpio = {.port = config->gpio_index, .pin = pin}; + int32_t int_no = SL_GPIO_INTERRUPT_UNAVAILABLE; + sl_gpio_interrupt_flag_t flag = SL_GPIO_INTERRUPT_RISING_FALLING_EDGE; + + if (mode == GPIO_INT_MODE_LEVEL) { + LOG_ERR("Level interrupt not supported on pin %u", pin); + return -ENOTSUP; + } + + if (mode == GPIO_INT_MODE_DISABLED) { + ARRAY_FOR_EACH(common->irq_pin_map, i) { + if ((data->int_enabled_mask & BIT(i)) && (common->irq_pin_map[i] == pin)) { + sl_hal_gpio_disable_interrupts(BIT(i)); + WRITE_BIT(data->int_enabled_mask, i, false); + common->irq_pin_map[i] = 0xFF; + break; + } + } + } else { + /* Check if pin already has an interrupt configured */ + ARRAY_FOR_EACH(common->irq_pin_map, i) { + if ((data->int_enabled_mask & BIT(i)) && (common->irq_pin_map[i] == pin)) { + int_no = i; + break; + } + } + + if (trig == GPIO_INT_TRIG_LOW) { + flag = SL_GPIO_INTERRUPT_FALLING_EDGE; + } else if (trig == GPIO_INT_TRIG_HIGH) { + flag = SL_GPIO_INTERRUPT_RISING_EDGE; + } else { + flag = SL_GPIO_INTERRUPT_RISING_FALLING_EDGE; + } + + int_no = sl_hal_gpio_configure_external_interrupt(&gpio, int_no, flag); + + if (int_no == SL_GPIO_INTERRUPT_UNAVAILABLE) { + LOG_ERR("No available interrupt for pin %u", pin); + return -EINVAL; + } + + common->irq_pin_map[int_no] = pin; + + sl_hal_gpio_enable_interrupts(BIT(int_no)); + WRITE_BIT(data->int_enabled_mask, int_no, true); + } + + return 0; +} + +static int gpio_silabs_port_manage_callback(const struct device *dev, struct gpio_callback *cb, + bool set) +{ + struct gpio_silabs_port_data *data = dev->data; + + return gpio_manage_callback(&data->callbacks, cb, set); +} + +static void gpio_silabs_common_isr(const struct device *dev) +{ + struct gpio_silabs_common_data *data = dev->data; + uint32_t int_status = GPIO->IF; + + ARRAY_FOR_EACH(data->ports, i) { + if (!int_status) { + break; + } + const struct device *port_dev = data->ports[i]; + struct gpio_silabs_port_data *port_data = port_dev->data; + uint32_t enabled_int = int_status & port_data->int_enabled_mask; + + if (enabled_int) { + uint32_t pin_mask = 0; + + ARRAY_FOR_EACH(data->irq_pin_map, int_line) { + if ((enabled_int & BIT(int_line)) && + (data->irq_pin_map[int_line] != 0xFF)) { + pin_mask |= BIT(data->irq_pin_map[int_line]); + } + } + + GPIO->IF_CLR = enabled_int; + if (pin_mask) { + gpio_fire_callbacks(&port_data->callbacks, port_dev, pin_mask); + } + int_status &= ~enabled_int; + } + } +} + +static DEVICE_API(gpio, gpio_driver_api) = { + .pin_configure = gpio_silabs_pin_configure, +#ifdef CONFIG_GPIO_GET_CONFIG + .pin_get_config = gpio_silabs_pin_get_config, +#endif + .port_get_raw = gpio_silabs_port_get_raw, + .port_set_masked_raw = gpio_silabs_port_set_masked_raw, + .port_set_bits_raw = gpio_silabs_port_set_bits_raw, + .port_clear_bits_raw = gpio_silabs_port_clear_bits_raw, + .port_toggle_bits = gpio_silabs_port_toggle_bits, + .pin_interrupt_configure = gpio_silabs_pin_interrupt_configure, + .manage_callback = gpio_silabs_port_manage_callback, +}; + +static DEVICE_API(gpio, gpio_common_driver_api) = { + .manage_callback = gpio_silabs_port_manage_callback, +}; + +static struct gpio_silabs_common_data gpio_silabs_common_data_inst; + +static int gpio_silabs_common_init(const struct device *dev) +{ + const struct gpio_silabs_common_config *cfg = dev->config; + struct gpio_silabs_common_data *data = dev->data; + int ret; + + /* Enable clock */ + ret = clock_control_on(cfg->clock, (clock_control_subsys_t)&cfg->clock_cfg); + if (ret < 0) { + return ret; + } + + ARRAY_FOR_EACH(data->irq_pin_map, i) { + data->irq_pin_map[i] = 0xFF; + } + + if (cfg->irq_connect) { + cfg->irq_connect(dev); + } + + LOG_DBG("Silabs GPIO common init complete"); + return 0; +} + +#define GPIO_PORT_INIT(n) \ + static int gpio_silabs_port_##n##_init(const struct device *dev) \ + { \ + struct gpio_silabs_port_data *data = dev->data; \ + data->common_dev = DEVICE_DT_GET(DT_PARENT(n)); \ + gpio_silabs_add_port(&gpio_silabs_common_data_inst, dev); \ + return 0; \ + } \ + static const struct gpio_silabs_port_config gpio_silabs_port_##n##_config = { \ + .common = {.port_pin_mask = (gpio_port_pins_t)(-1)}, \ + .gpio_index = GET_SILABS_GPIO_INDEX(n), \ + }; \ + static struct gpio_silabs_port_data gpio_silabs_port_##n##_data; \ + DEVICE_DT_DEFINE(n, gpio_silabs_port_##n##_init, NULL, &gpio_silabs_port_##n##_data, \ + &gpio_silabs_port_##n##_config, PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, \ + &gpio_driver_api); + +#define GPIO_CONTROLLER_INIT(idx) \ + static void gpio_silabs_irq_connect_##idx(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(idx, gpio_even, irq), \ + DT_INST_IRQ_BY_NAME(idx, gpio_even, priority), gpio_silabs_common_isr, \ + DEVICE_DT_INST_GET(idx), 0); \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(idx, gpio_odd, irq), \ + DT_INST_IRQ_BY_NAME(idx, gpio_odd, priority), gpio_silabs_common_isr, \ + DEVICE_DT_INST_GET(idx), 0); \ + irq_enable(DT_INST_IRQ_BY_NAME(idx, gpio_even, irq)); \ + irq_enable(DT_INST_IRQ_BY_NAME(idx, gpio_odd, irq)); \ + } \ + static const struct gpio_silabs_common_config gpio_silabs_common_config_##idx = { \ + .irq_connect = gpio_silabs_irq_connect_##idx, \ + .clock = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(idx)), \ + .clock_cfg = SILABS_DT_INST_CLOCK_CFG(idx), \ + }; \ + DEVICE_DT_INST_DEFINE(idx, gpio_silabs_common_init, NULL, &gpio_silabs_common_data_inst, \ + &gpio_silabs_common_config_##idx, PRE_KERNEL_1, \ + CONFIG_GPIO_SILABS_COMMON_INIT_PRIORITY, &gpio_common_driver_api); \ + DT_INST_FOREACH_CHILD_STATUS_OKAY(idx, GPIO_PORT_INIT) + +DT_INST_FOREACH_STATUS_OKAY(GPIO_CONTROLLER_INIT) diff --git a/dts/arm/silabs/xg21/xg21.dtsi b/dts/arm/silabs/xg21/xg21.dtsi index 7d5a4d023bb0..8d5c44bd9c9b 100644 --- a/dts/arm/silabs/xg21/xg21.dtsi +++ b/dts/arm/silabs/xg21/xg21.dtsi @@ -336,7 +336,7 @@ }; gpio: gpio@5003c300 { - compatible = "silabs,gecko-gpio"; + compatible = "silabs,gpio"; reg = <0x5003c300 0x440>; interrupts = <26 2>, <25 2>; interrupt-names = "GPIO_EVEN", "GPIO_ODD"; @@ -347,36 +347,32 @@ #size-cells = <1>; gpioa: gpio@5003c000 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003c000 0x30>; - peripheral-id = <0>; gpio-controller; #gpio-cells = <2>; status = "disabled"; }; gpiob: gpio@5003c030 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003c030 0x30>; - peripheral-id = <1>; gpio-controller; #gpio-cells = <2>; status = "disabled"; }; gpioc: gpio@5003c060 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003c060 0x30>; - peripheral-id = <2>; gpio-controller; #gpio-cells = <2>; status = "disabled"; }; gpiod: gpio@5003c090 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003c090 0x30>; - peripheral-id = <3>; gpio-controller; #gpio-cells = <2>; status = "disabled"; diff --git a/dts/arm/silabs/xg22/xg22.dtsi b/dts/arm/silabs/xg22/xg22.dtsi index 46999ec099dd..a49372a92514 100644 --- a/dts/arm/silabs/xg22/xg22.dtsi +++ b/dts/arm/silabs/xg22/xg22.dtsi @@ -400,7 +400,7 @@ }; gpio: gpio@5003c000 { - compatible = "silabs,gecko-gpio"; + compatible = "silabs,gpio"; reg = <0x5003C000 0x440>; ranges; interrupts = <25 2>, <26 2>; @@ -410,7 +410,7 @@ #size-cells = <1>; gpioa: gpio@5003c000 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003C000 0x30>; gpio-controller; #gpio-cells = <2>; @@ -418,7 +418,7 @@ }; gpiob: gpio@5003c030 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003C030 0x30>; gpio-controller; #gpio-cells = <2>; @@ -426,7 +426,7 @@ }; gpioc: gpio@5003c060 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003C060 0x30>; gpio-controller; #gpio-cells = <2>; @@ -434,7 +434,7 @@ }; gpiod: gpio@5003c090 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003C090 0x30>; gpio-controller; #gpio-cells = <2>; diff --git a/dts/arm/silabs/xg23/xg23.dtsi b/dts/arm/silabs/xg23/xg23.dtsi index 64a47f020f8f..8213dab47423 100644 --- a/dts/arm/silabs/xg23/xg23.dtsi +++ b/dts/arm/silabs/xg23/xg23.dtsi @@ -457,7 +457,7 @@ }; gpio: gpio@5003c000 { - compatible = "silabs,gecko-gpio"; + compatible = "silabs,gpio"; reg = <0x5003c000 0x4000>; interrupts = <27 2>, <26 2>; interrupt-names = "GPIO_EVEN", "GPIO_ODD"; @@ -468,36 +468,32 @@ #size-cells = <1>; gpioa: gpio@5003c030 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003c030 0x30>; - peripheral-id = <0>; gpio-controller; #gpio-cells = <2>; status = "disabled"; }; gpiob: gpio@5003c060 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003c060 0x30>; - peripheral-id = <1>; gpio-controller; #gpio-cells = <2>; status = "disabled"; }; gpioc: gpio@5003c090 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003c090 0x30>; - peripheral-id = <2>; gpio-controller; #gpio-cells = <2>; status = "disabled"; }; gpiod: gpio@5003c0C0 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003c0C0 0x30>; - peripheral-id = <3>; gpio-controller; #gpio-cells = <2>; status = "disabled"; diff --git a/dts/arm/silabs/xg24/xg24.dtsi b/dts/arm/silabs/xg24/xg24.dtsi index 147f1e639e60..13c9c3cbce3f 100644 --- a/dts/arm/silabs/xg24/xg24.dtsi +++ b/dts/arm/silabs/xg24/xg24.dtsi @@ -427,7 +427,7 @@ }; gpio: gpio@5003c000 { - compatible = "silabs,gecko-gpio"; + compatible = "silabs,gpio"; reg = <0x5003c000 0x440>; interrupts = <26 2>, <25 2>; interrupt-names = "GPIO_EVEN", "GPIO_ODD"; @@ -438,36 +438,32 @@ #size-cells = <1>; gpioa: gpio@5003c030 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003c030 0x30>; - peripheral-id = <0>; gpio-controller; #gpio-cells = <2>; status = "disabled"; }; gpiob: gpio@5003c060 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003c060 0x30>; - peripheral-id = <1>; gpio-controller; #gpio-cells = <2>; status = "disabled"; }; gpioc: gpio@5003c090 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003c090 0x30>; - peripheral-id = <2>; gpio-controller; #gpio-cells = <2>; status = "disabled"; }; gpiod: gpio@5003c0C0 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003c0C0 0x30>; - peripheral-id = <3>; gpio-controller; #gpio-cells = <2>; status = "disabled"; diff --git a/dts/arm/silabs/xg27/xg27.dtsi b/dts/arm/silabs/xg27/xg27.dtsi index d2d08d7d48c5..bf6d07a46ed7 100644 --- a/dts/arm/silabs/xg27/xg27.dtsi +++ b/dts/arm/silabs/xg27/xg27.dtsi @@ -409,7 +409,7 @@ }; gpio: gpio@5003c000 { - compatible = "silabs,gecko-gpio"; + compatible = "silabs,gpio"; reg = <0x5003C000 0x440>; interrupts = <30 2>, <31 2>; interrupt-names = "gpio_odd", "gpio_even"; @@ -419,7 +419,7 @@ #size-cells = <1>; gpioa: gpio@5003c030 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003C030 0x30>; gpio-controller; #gpio-cells = <2>; @@ -427,7 +427,7 @@ }; gpiob: gpio@5003c060 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003C060 0x30>; gpio-controller; #gpio-cells = <2>; @@ -435,7 +435,7 @@ }; gpioc: gpio@5003c090 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003C090 0x30>; gpio-controller; #gpio-cells = <2>; @@ -443,7 +443,7 @@ }; gpiod: gpio@5003c0c0 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003C0C0 0x30>; gpio-controller; #gpio-cells = <2>; diff --git a/dts/arm/silabs/xg28/xg28.dtsi b/dts/arm/silabs/xg28/xg28.dtsi index fce4bf073863..1637c8d58595 100644 --- a/dts/arm/silabs/xg28/xg28.dtsi +++ b/dts/arm/silabs/xg28/xg28.dtsi @@ -471,7 +471,7 @@ }; gpio: gpio@5003c000 { - compatible = "silabs,gecko-gpio"; + compatible = "silabs,gpio"; reg = <0x5003c000 0x4000>; interrupts = <27 2>, <26 2>; interrupt-names = "GPIO_EVEN", "GPIO_ODD"; @@ -482,36 +482,32 @@ #size-cells = <1>; gpioa: gpio@5003c030 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003c030 0x30>; - peripheral-id = <0>; gpio-controller; #gpio-cells = <2>; status = "disabled"; }; gpiob: gpio@5003c060 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003c060 0x30>; - peripheral-id = <1>; gpio-controller; #gpio-cells = <2>; status = "disabled"; }; gpioc: gpio@5003c090 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003c090 0x30>; - peripheral-id = <2>; gpio-controller; #gpio-cells = <2>; status = "disabled"; }; gpiod: gpio@5003c0c0 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003c0c0 0x30>; - peripheral-id = <3>; gpio-controller; #gpio-cells = <2>; status = "disabled"; diff --git a/dts/arm/silabs/xg29/xg29.dtsi b/dts/arm/silabs/xg29/xg29.dtsi index 543201418f6f..db155d3dac47 100644 --- a/dts/arm/silabs/xg29/xg29.dtsi +++ b/dts/arm/silabs/xg29/xg29.dtsi @@ -279,7 +279,7 @@ }; gpio: gpio@5003c000 { - compatible = "silabs,gecko-gpio"; + compatible = "silabs,gpio"; reg = <0x5003C000 0x440>; interrupts = <31 2>, <30 2>; interrupt-names = "GPIO_EVEN", "GPIO_ODD"; @@ -289,7 +289,7 @@ #size-cells = <1>; gpioa: gpio@5003c030 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003C030 0x30>; gpio-controller; #gpio-cells = <2>; @@ -297,7 +297,7 @@ }; gpiob: gpio@5003c060 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003C060 0x30>; gpio-controller; #gpio-cells = <2>; @@ -305,7 +305,7 @@ }; gpioc: gpio@5003c090 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003C090 0x30>; gpio-controller; #gpio-cells = <2>; @@ -313,7 +313,7 @@ }; gpiod: gpio@5003c0c0 { - compatible = "silabs,gecko-gpio-port"; + compatible = "silabs,gpio-port"; reg = <0x5003C0C0 0x30>; gpio-controller; #gpio-cells = <2>; diff --git a/dts/bindings/gpio/silabs,gpio-port.yaml b/dts/bindings/gpio/silabs,gpio-port.yaml new file mode 100644 index 000000000000..25aa379171ba --- /dev/null +++ b/dts/bindings/gpio/silabs,gpio-port.yaml @@ -0,0 +1,19 @@ +title: Silicon Labs Series 2 GPIO (General Purpose Input/Output) Port + +description: | + Single GPIO port on Silicon Labs EFR32 Series 2. + +compatible: "silabs,gpio-port" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#gpio-cells": + const: 2 + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/gpio/silabs,gpio.yaml b/dts/bindings/gpio/silabs,gpio.yaml new file mode 100644 index 000000000000..dc5ccb28ac5d --- /dev/null +++ b/dts/bindings/gpio/silabs,gpio.yaml @@ -0,0 +1,15 @@ +title: Silicon Labs Series 2 GPIO (General Purpose Input/Output) Peripheral + +description: | + GPIO peripheral for Silicon Labs EFR32 Series 2. + +compatible: "silabs,gpio" + +include: base.yaml + +properties: + reg: + required: true + + interrupts: + required: true diff --git a/modules/hal_silabs/simplicity_sdk/CMakeLists.txt b/modules/hal_silabs/simplicity_sdk/CMakeLists.txt index f65f6e3720d4..07ab823fe558 100644 --- a/modules/hal_silabs/simplicity_sdk/CMakeLists.txt +++ b/modules/hal_silabs/simplicity_sdk/CMakeLists.txt @@ -276,6 +276,16 @@ if(CONFIG_SOC_GECKO_GPIO) ) endif() +if(CONFIG_SILABS_SISDK_GPIO) + zephyr_library_sources( + ${PERIPHERAL_DIR}/src/sl_hal_gpio.c + ) + zephyr_library_compile_definitions( + SL_CATALOG_GPIO_PRESENT + SL_CODE_COMPONENT_HAL_GPIO=hal_gpio + ) +endif() + zephyr_library_sources_ifdef(CONFIG_SILABS_SISDK_LETIMER ${PERIPHERAL_DIR}/src/sl_hal_letimer.c) zephyr_library_sources_ifdef(CONFIG_SILABS_SISDK_TIMER ${PERIPHERAL_DIR}/src/sl_hal_timer.c) diff --git a/modules/hal_silabs/simplicity_sdk/Kconfig b/modules/hal_silabs/simplicity_sdk/Kconfig index cb670e77fdf2..05764b15f330 100644 --- a/modules/hal_silabs/simplicity_sdk/Kconfig +++ b/modules/hal_silabs/simplicity_sdk/Kconfig @@ -4,6 +4,9 @@ menu "SiSDK configuration" depends on HAS_SILABS_SISDK +config SILABS_SISDK_GPIO + bool "Peripheral HAL for GPIO" + config SILABS_SISDK_LETIMER bool "Peripheral HAL for LETIMER" diff --git a/soc/silabs/silabs_s2/xg21/Kconfig.defconfig b/soc/silabs/silabs_s2/xg21/Kconfig.defconfig index 06304e1c25bf..e262e4df55d4 100644 --- a/soc/silabs/silabs_s2/xg21/Kconfig.defconfig +++ b/soc/silabs/silabs_s2/xg21/Kconfig.defconfig @@ -11,8 +11,4 @@ config PM select COUNTER select UART_INTERRUPT_DRIVEN -config GPIO_GECKO - default y - depends on GPIO || LOG_BACKEND_SWO - endif diff --git a/soc/silabs/silabs_s2/xg22/Kconfig.defconfig b/soc/silabs/silabs_s2/xg22/Kconfig.defconfig index 3690a957c36c..7a63d524a7c2 100644 --- a/soc/silabs/silabs_s2/xg22/Kconfig.defconfig +++ b/soc/silabs/silabs_s2/xg22/Kconfig.defconfig @@ -10,7 +10,4 @@ config NUM_IRQS config PM select UART_INTERRUPT_DRIVEN -config GPIO_GECKO - default y - endif diff --git a/soc/silabs/silabs_s2/xg23/Kconfig.defconfig b/soc/silabs/silabs_s2/xg23/Kconfig.defconfig index 8c695729f9ae..a391d7619749 100644 --- a/soc/silabs/silabs_s2/xg23/Kconfig.defconfig +++ b/soc/silabs/silabs_s2/xg23/Kconfig.defconfig @@ -10,7 +10,4 @@ config NUM_IRQS config PM select UART_INTERRUPT_DRIVEN -config GPIO_GECKO - default y - endif diff --git a/soc/silabs/silabs_s2/xg27/Kconfig b/soc/silabs/silabs_s2/xg27/Kconfig index fb825b991c59..7e9a584dfd96 100644 --- a/soc/silabs/silabs_s2/xg27/Kconfig +++ b/soc/silabs/silabs_s2/xg27/Kconfig @@ -11,6 +11,7 @@ config SOC_SILABS_XG27 select CPU_HAS_FPU select HAS_SWO select SOC_GECKO_CMU + select SOC_GECKO_GPIO select SOC_GECKO_CORE select SOC_GECKO_DEV_INIT select SOC_GECKO_SE diff --git a/soc/silabs/silabs_s2/xg27/Kconfig.defconfig b/soc/silabs/silabs_s2/xg27/Kconfig.defconfig index b6542d0ab29c..cc702c1e77b0 100644 --- a/soc/silabs/silabs_s2/xg27/Kconfig.defconfig +++ b/soc/silabs/silabs_s2/xg27/Kconfig.defconfig @@ -7,7 +7,4 @@ config NUM_IRQS # must be >= the highest interrupt number used default 66 -config GPIO_GECKO - default y - endif diff --git a/tests/drivers/gpio/gpio_api_1pin/boards/xg29_rb4412a.overlay b/tests/drivers/gpio/gpio_api_1pin/boards/xg29_rb4412a.overlay new file mode 100644 index 000000000000..4bed8a07c940 --- /dev/null +++ b/tests/drivers/gpio/gpio_api_1pin/boards/xg29_rb4412a.overlay @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Silicon Laboratories Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + led0 = &led0; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpioc 7 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&gpioc { + status = "okay"; +};