diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index bb6ccecc57..5b1229fd00 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -81,6 +81,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_NUMICRO gpio_numicro.c) zephyr_library_sources_ifdef(CONFIG_GPIO_HOGS gpio_hogs.c) zephyr_library_sources_ifdef(CONFIG_GPIO_NUMAKER gpio_numaker.c) zephyr_library_sources_ifdef(CONFIG_GPIO_EFINIX_SAPPHIRE gpio_efinix_sapphire.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_DAVINCI gpio_davinci.c) if (CONFIG_GPIO_EMUL_SDL) zephyr_library_sources(gpio_emul_sdl.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 3e73eab3d9..7e368a9852 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -203,4 +203,6 @@ source "drivers/gpio/Kconfig.numaker" source "drivers/gpio/Kconfig.efinix_sapphire" +source "drivers/gpio/Kconfig.davinci" + endif # GPIO diff --git a/drivers/gpio/Kconfig.davinci b/drivers/gpio/Kconfig.davinci new file mode 100644 index 0000000000..2bd94cade4 --- /dev/null +++ b/drivers/gpio/Kconfig.davinci @@ -0,0 +1,11 @@ +# Copyright (C) 2023 BeagleBoard.org Foundation +# Copyright (C) 2023 S Prashanth +# +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_DAVINCI + bool "Davinci GPIO Driver" + default y + depends on DT_HAS_TI_DAVINCI_GPIO_ENABLED + help + Enable the Davinci GPIO controller support. diff --git a/drivers/gpio/gpio_davinci.c b/drivers/gpio/gpio_davinci.c new file mode 100644 index 0000000000..5726ed1bf3 --- /dev/null +++ b/drivers/gpio/gpio_davinci.c @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2023 BeagleBoard.org Foundation + * Copyright (C) 2023 S Prashanth + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ti_davinci_gpio + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Helper Macros for GPIO */ +#define DEV_CFG(dev) \ + ((const struct gpio_davinci_config * const)((dev)->config)) +#define DEV_DATA(dev) ((struct gpio_davinci_data *)(dev)->data) +#define DEV_GPIO_CFG_BASE(dev) \ + ((struct gpio_davinci_regs *)DEVICE_MMIO_NAMED_GET(dev, port_base)) + +#define GPIO_DAVINCI_DIR_RESET_VAL (0xFFFFFFFF) + +struct gpio_davinci_regs { + uint32_t dir; + uint32_t out_data; + uint32_t set_data; + uint32_t clr_data; + uint32_t in_data; + uint32_t set_ris_trig; + uint32_t clr_ris_trig; + uint32_t set_fal_trig; + uint32_t clr_fal_trig; + uint32_t intstat; +}; + +struct gpio_davinci_data { + struct gpio_driver_data common; + + DEVICE_MMIO_NAMED_RAM(port_base); + + sys_slist_t cb; +}; + +struct gpio_davinci_config { + void (*bank_config)(const struct device *dev); + struct gpio_driver_config common; + + DEVICE_MMIO_NAMED_ROM(port_base); + + uint32_t port_num; +}; + +static int gpio_davinci_configure(const struct device *dev, gpio_pin_t pin, + gpio_flags_t flags) +{ + volatile struct gpio_davinci_regs *regs = DEV_GPIO_CFG_BASE(dev); + + if ((flags & GPIO_SINGLE_ENDED) != 0) { + return -ENOTSUP; + } + + if ((flags & (GPIO_PULL_UP | GPIO_PULL_DOWN)) != 0) { + return -ENOTSUP; + } + + if ((flags & GPIO_OUTPUT) != 0) { + if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) { + regs->set_data = BIT(pin); + } else { + regs->clr_data = BIT(pin); + } + + regs->dir &= (~(BIT(pin))); + + } else { + regs->dir |= (BIT(pin)); + } + + return 0; +} + +static int gpio_davinci_port_get_raw(const struct device *dev, + gpio_port_value_t *value) +{ + volatile struct gpio_davinci_regs *regs = DEV_GPIO_CFG_BASE(dev); + + *value = regs->in_data; + + return 0; +} + +static int gpio_davinci_port_set_masked_raw(const struct device *dev, + gpio_port_pins_t mask, gpio_port_value_t value) +{ + volatile struct gpio_davinci_regs *regs = DEV_GPIO_CFG_BASE(dev); + + regs->out_data = (regs->out_data & (~mask)) | (mask & value); + + return 0; +} + +static int gpio_davinci_port_set_bits_raw(const struct device *dev, + gpio_port_pins_t mask) +{ + volatile struct gpio_davinci_regs *regs = DEV_GPIO_CFG_BASE(dev); + + regs->set_data |= mask; + + return 0; +} + +static int gpio_davinci_port_clear_bits_raw(const struct device *dev, + gpio_port_pins_t mask) +{ + volatile struct gpio_davinci_regs *regs = DEV_GPIO_CFG_BASE(dev); + + regs->clr_data |= mask; + + return 0; +} + +static int gpio_davinci_port_toggle_bits(const struct device *dev, + gpio_port_pins_t mask) +{ + volatile struct gpio_davinci_regs *regs = DEV_GPIO_CFG_BASE(dev); + + regs->out_data ^= mask; + + return 0; +} + +static const struct gpio_driver_api gpio_davinci_driver_api = { + .pin_configure = gpio_davinci_configure, + .port_get_raw = gpio_davinci_port_get_raw, + .port_set_masked_raw = gpio_davinci_port_set_masked_raw, + .port_set_bits_raw = gpio_davinci_port_set_bits_raw, + .port_clear_bits_raw = gpio_davinci_port_clear_bits_raw, + .port_toggle_bits = gpio_davinci_port_toggle_bits +}; + +static int gpio_davinci_init(const struct device *dev) +{ + const struct gpio_davinci_config *config = DEV_CFG(dev); + volatile struct gpio_davinci_regs *regs = DEV_GPIO_CFG_BASE(dev); + + DEVICE_MMIO_NAMED_MAP(dev, port_base, K_MEM_CACHE_NONE); + + regs->dir = GPIO_DAVINCI_DIR_RESET_VAL; + + config->bank_config(dev); + + return 0; +} + +#define GPIO_DAVINCI_INIT_FUNC(n) \ + static void gpio_davinci_bank_##n##_config(const struct device *dev) \ + { \ + volatile struct gpio_davinci_regs *regs = DEV_GPIO_CFG_BASE(dev); \ + ARG_UNUSED(regs); \ + } + +#define GPIO_DAVINCI_DEVICE_INIT(n) \ + DEVICE_DT_INST_DEFINE(n, &gpio_davinci_##n##_init, \ + NULL, &gpio_davinci_##n##_data, \ + &gpio_davinci_##n##_config, \ + POST_KERNEL, CONFIG_GPIO_INIT_PRIORITY, \ + &api_funcs) + +#define GPIO_DAVINCI_INIT(n) \ + \ + GPIO_DAVINCI_INIT_FUNC(n) \ + static const struct gpio_davinci_config gpio_davinci_##n##_config = { \ + .bank_config = gpio_davinci_bank_##n##_config, \ + .common = { \ + .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \ + }, \ + DEVICE_MMIO_NAMED_ROM_INIT(port_base, DT_DRV_INST(n)), \ + .port_num = n \ + }; \ + \ + static struct gpio_davinci_data gpio_davinci_##n##_data; \ + \ + DEVICE_DT_INST_DEFINE(n, \ + &gpio_davinci_init, \ + NULL, \ + &gpio_davinci_##n##_data, \ + &gpio_davinci_##n##_config, \ + PRE_KERNEL_2, \ + CONFIG_GPIO_INIT_PRIORITY, \ + &gpio_davinci_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(GPIO_DAVINCI_INIT) diff --git a/dts/bindings/gpio/ti,davinci-gpio-nexus.yaml b/dts/bindings/gpio/ti,davinci-gpio-nexus.yaml new file mode 100644 index 0000000000..3cfccfa5ee --- /dev/null +++ b/dts/bindings/gpio/ti,davinci-gpio-nexus.yaml @@ -0,0 +1,18 @@ +# Copyright (C) 2023 BeagleBoard.org Foundation +# Copyright (C) 2023 S Prashanth +# +# SPDX-License-Identifier: Apache-2.0 + +description: GPIO controller for Davinci and Keystone devices + +compatible: "ti,davinci-gpio-nexus" + +include: [base.yaml, gpio-nexus.yaml] + +properties: + "#gpio-cells": + const: 2 + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/gpio/ti,davinci-gpio.yaml b/dts/bindings/gpio/ti,davinci-gpio.yaml new file mode 100644 index 0000000000..0472dfa1aa --- /dev/null +++ b/dts/bindings/gpio/ti,davinci-gpio.yaml @@ -0,0 +1,21 @@ +# Copyright (C) 2023 BeagleBoard.org Foundation +# Copyright (C) 2023 S Prashanth +# +# SPDX-License-Identifier: Apache-2.0 + +description: GPIO controller for Davinci and Keystone devices. + +compatible: "ti,davinci-gpio" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#gpio-cells": + const: 2 + +gpio-cells: + - pin + - flags