diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index ad1a84fba91..fd948f46e10 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -99,6 +99,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_STELLARIS gpio_stellaris.c) zephyr_library_sources_ifdef(CONFIG_GPIO_STM32 gpio_stm32.c) zephyr_library_sources_ifdef(CONFIG_GPIO_STMPE1600 gpio_stmpe1600.c) zephyr_library_sources_ifdef(CONFIG_GPIO_SX1509B gpio_sx1509b.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_SY1XX gpio_sy1xx.c) zephyr_library_sources_ifdef(CONFIG_GPIO_TCA6424A gpio_tca6424a.c) zephyr_library_sources_ifdef(CONFIG_GPIO_TELINK_B91 gpio_b91.c) zephyr_library_sources_ifdef(CONFIG_GPIO_TEST gpio_test.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 84b12627af6..d641c18794a 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -183,6 +183,7 @@ source "drivers/gpio/Kconfig.stellaris" source "drivers/gpio/Kconfig.stm32" source "drivers/gpio/Kconfig.stmpe1600" source "drivers/gpio/Kconfig.sx1509b" +source "drivers/gpio/Kconfig.sy1xx" source "drivers/gpio/Kconfig.tca6424a" source "drivers/gpio/Kconfig.test" source "drivers/gpio/Kconfig.tle9104" diff --git a/drivers/gpio/Kconfig.sy1xx b/drivers/gpio/Kconfig.sy1xx new file mode 100644 index 00000000000..6fa452be854 --- /dev/null +++ b/drivers/gpio/Kconfig.sy1xx @@ -0,0 +1,9 @@ +# Copyright (c) 2024 sensry.io +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_SY1XX + bool "SY1XX GPIO driver" + default y + depends on DT_HAS_SENSRY_SY1XX_GPIO_ENABLED + help + Enable the SY1XX GPIO driver. diff --git a/drivers/gpio/gpio_sy1xx.c b/drivers/gpio/gpio_sy1xx.c new file mode 100644 index 00000000000..761ba84bad6 --- /dev/null +++ b/drivers/gpio/gpio_sy1xx.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2024 sensry.io + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT sensry_sy1xx_gpio + +#include +LOG_MODULE_REGISTER(sy1xx_gpio, CONFIG_GPIO_LOG_LEVEL); + +#include +#include +#include +#include +#include +#include +#include +#include + +#define SY1XX_GPIO_GET_OFFS 0x00 +#define SY1XX_GPIO_SET_OFFS 0x1c +#define SY1XX_GPIO_CLR_OFFS 0x20 + +struct sy1xx_gpio_config { + /* Base address for GPIO port*/ + uint32_t port_base_addr; + /* configuration base address for the pad config */ + uint32_t pad_cfg_offs; + /* mask of pins which are allowed to modify by the gpio driver */ + uint32_t pin_mask; +}; + +/* Function prototypes for the GPIO API */ +static int sy1xx_gpio_driver_configure(const struct device *dev, gpio_pin_t pin, + gpio_flags_t flags); +static int sy1xx_gpio_driver_port_get_raw(const struct device *dev, gpio_port_value_t *value); +static int sy1xx_gpio_driver_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask, + gpio_port_value_t value); +static int sy1xx_gpio_driver_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins); +static int sy1xx_gpio_driver_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins); +static int sy1xx_gpio_driver_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins); + +static int sy1xx_gpio_driver_init(const struct device *dev) +{ + return 0; +} + +int sy1xx_gpio_driver_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) +{ + const struct sy1xx_gpio_config *const cfg = dev->config; + + if (((BIT(pin)) & cfg->pin_mask) == 0) { + return -EINVAL; + } + + /* initialize the pinctrl config for the given gpio pin */ + pinctrl_soc_pin_t pcfg = { + .addr = cfg->pad_cfg_offs + ROUND_DOWN(pin, 4), + .iro = (pin % 4) * 8, + .cfg = 0, + }; + + /* translate gpio flags into pinctrl config */ + if (flags & GPIO_INPUT) { + + if (flags & GPIO_PULL_UP) { + pcfg.cfg |= BIT(SY1XX_PAD_PULL_UP_OFFS); + } + if (flags & GPIO_PULL_DOWN) { + pcfg.cfg |= BIT(SY1XX_PAD_PULL_DOWN_OFFS); + } + + } else if (flags & GPIO_OUTPUT) { + pcfg.cfg |= BIT(SY1XX_PAD_DIR_OFFS); + + if (flags & GPIO_OUTPUT_INIT_LOW) { + sy1xx_gpio_driver_port_set_masked_raw(dev, BIT(pin), 0); + } + if (flags & GPIO_OUTPUT_INIT_HIGH) { + sy1xx_gpio_driver_port_set_masked_raw(dev, BIT(pin), BIT(pin)); + } + + } else if (flags == GPIO_DISCONNECTED) { + pcfg.cfg |= BIT(SY1XX_PAD_TRISTATE_OFFS); + + } else { + LOG_ERR("%s: unsupported pinctrl mode for pin: %u", dev->name, pin); + return -ENOTSUP; + } + + /* PAD config */ + int32_t ret = pinctrl_configure_pins(&pcfg, 1, PINCTRL_STATE_DEFAULT); + + if (ret != 0) { + LOG_ERR("%s: failed to apply pinctrl for pin: %u", dev->name, pin); + return -EINVAL; + } + + return 0; +} + +int sy1xx_gpio_driver_port_get_raw(const struct device *dev, gpio_port_value_t *value) +{ + const struct sy1xx_gpio_config *const cfg = dev->config; + + *value = sys_read32(cfg->port_base_addr | SY1XX_GPIO_GET_OFFS); + return 0; +} + +int sy1xx_gpio_driver_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask, + gpio_port_value_t value) +{ + const struct sy1xx_gpio_config *const cfg = dev->config; + + uint32_t set_mask = (mask & value) & (cfg->pin_mask); + uint32_t clr_mask = (mask & (~value)) & (cfg->pin_mask); + + sy1xx_gpio_driver_port_set_bits_raw(dev, set_mask); + sy1xx_gpio_driver_port_clear_bits_raw(dev, clr_mask); + return 0; +} + +int sy1xx_gpio_driver_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + const struct sy1xx_gpio_config *const cfg = dev->config; + + /* affects only pins that are set to logical '1' */ + sys_write32((uint32_t)pins, cfg->port_base_addr | SY1XX_GPIO_SET_OFFS); + return 0; +} + +int sy1xx_gpio_driver_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + const struct sy1xx_gpio_config *const cfg = dev->config; + + /* affects only pins that are set to logical '1' */ + sys_write32((uint32_t)pins, cfg->port_base_addr | SY1XX_GPIO_CLR_OFFS); + return 0; +} + +int sy1xx_gpio_driver_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins) +{ + const struct sy1xx_gpio_config *const cfg = dev->config; + + uint32_t current = sys_read32(cfg->port_base_addr | SY1XX_GPIO_GET_OFFS); + + sy1xx_gpio_driver_port_set_masked_raw(dev, pins, ~current); + return 0; +} + +/* Define the GPIO API structure */ +static const struct gpio_driver_api sy1xx_gpio_driver_api = { + .pin_configure = sy1xx_gpio_driver_configure, + .port_get_raw = sy1xx_gpio_driver_port_get_raw, + .port_set_masked_raw = sy1xx_gpio_driver_port_set_masked_raw, + .port_set_bits_raw = sy1xx_gpio_driver_port_set_bits_raw, + .port_clear_bits_raw = sy1xx_gpio_driver_port_clear_bits_raw, + .port_toggle_bits = sy1xx_gpio_driver_port_toggle_bits, +}; + +#define SY1XX_GPIO_INIT(n) \ + \ + static const struct sy1xx_gpio_config sy1xx_gpio_##n##_config = { \ + .port_base_addr = (uint32_t)DT_INST_REG_ADDR_BY_IDX(n, 0), \ + .pad_cfg_offs = (uint32_t)DT_INST_PROP(n, pad_cfg), \ + .pin_mask = (uint32_t)GPIO_PORT_PIN_MASK_FROM_DT_INST(n)}; \ + \ + DEVICE_DT_INST_DEFINE(n, sy1xx_gpio_driver_init, NULL, NULL, &sy1xx_gpio_##n##_config, \ + PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, &sy1xx_gpio_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(SY1XX_GPIO_INIT) diff --git a/dts/bindings/gpio/sensry,sy1xx-gpio.yaml b/dts/bindings/gpio/sensry,sy1xx-gpio.yaml new file mode 100644 index 00000000000..a66d8d7d83a --- /dev/null +++ b/dts/bindings/gpio/sensry,sy1xx-gpio.yaml @@ -0,0 +1,25 @@ +# Copyright (c) 2024 sensry.io +# SPDX-License-Identifier: Apache-2.0 + +description: Sensry SY1XX GPIO PORT node + +compatible: "sensry,sy1xx-gpio" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + description: Base address for the gpio configuration. + + "#gpio-cells": + const: 2 + + pad-cfg: + type: int + required: true + description: Offset for gpio pad ctrl registers. + +gpio-cells: + - pin + - flags