From 7fccb646cddf248846923c73911e2a585e6c02ca Mon Sep 17 00:00:00 2001 From: Audun Korneliussen Date: Fri, 20 Sep 2024 10:39:24 +0200 Subject: [PATCH] drivers: gpio: npm2100: Add driver for npm2100 pmic Add gpio driver for npm2100 pmic. Signed-off-by: Audun Korneliussen --- drivers/gpio/CMakeLists.txt | 1 + drivers/gpio/Kconfig | 1 + drivers/gpio/Kconfig.npm2100 | 19 ++ drivers/gpio/gpio_npm2100.c | 182 ++++++++++++++++++ dts/bindings/gpio/nordic,npm2100-gpio.yaml | 12 ++ .../dt-bindings/gpio/nordic-npm2100-gpio.h | 61 ++++++ tests/drivers/build_all/gpio/app.overlay | 16 +- 7 files changed, 290 insertions(+), 2 deletions(-) create mode 100644 drivers/gpio/Kconfig.npm2100 create mode 100644 drivers/gpio/gpio_npm2100.c create mode 100644 dts/bindings/gpio/nordic,npm2100-gpio.yaml create mode 100644 include/zephyr/dt-bindings/gpio/nordic-npm2100-gpio.h diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index ab188342539..7db261845e9 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -59,6 +59,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_NCT38XX_ALERT gpio_nct38xx_alert.c) zephyr_library_sources_ifdef(CONFIG_GPIO_NEORV32 gpio_neorv32.c) zephyr_library_sources_ifdef(CONFIG_GPIO_NPCX gpio_npcx.c) zephyr_library_sources_ifdef(CONFIG_GPIO_NPM1300 gpio_npm1300.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_NPM2100 gpio_npm2100.c) zephyr_library_sources_ifdef(CONFIG_GPIO_NPM6001 gpio_npm6001.c) zephyr_library_sources_ifdef(CONFIG_GPIO_NRFX gpio_nrfx.c) zephyr_library_sources_ifdef(CONFIG_GPIO_NUMAKER gpio_numaker.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index c7928055ac4..b944a2f5f71 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -146,6 +146,7 @@ source "drivers/gpio/Kconfig.nct38xx" source "drivers/gpio/Kconfig.neorv32" source "drivers/gpio/Kconfig.npcx" source "drivers/gpio/Kconfig.npm1300" +source "drivers/gpio/Kconfig.npm2100" source "drivers/gpio/Kconfig.npm6001" source "drivers/gpio/Kconfig.nrfx" source "drivers/gpio/Kconfig.numaker" diff --git a/drivers/gpio/Kconfig.npm2100 b/drivers/gpio/Kconfig.npm2100 new file mode 100644 index 00000000000..8adba8db214 --- /dev/null +++ b/drivers/gpio/Kconfig.npm2100 @@ -0,0 +1,19 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_NPM2100 + bool "nPM2100 GPIO driver" + default y + depends on DT_HAS_NORDIC_NPM2100_GPIO_ENABLED + select I2C + select MFD + help + Enable the nPM2100 GPIO driver. + +config GPIO_NPM2100_INIT_PRIORITY + int "nPM2100 GPIO driver initialization priority" + depends on GPIO_NPM2100 + default 80 + help + Initialization priority for the nPM2100 GPIO driver. It must be + greater than the I2C controller init priority. diff --git a/drivers/gpio/gpio_npm2100.c b/drivers/gpio/gpio_npm2100.c new file mode 100644 index 00000000000..da7b649e29a --- /dev/null +++ b/drivers/gpio/gpio_npm2100.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nordic_npm2100_gpio + +#include + +#include +#include +#include +#include +#include +#include + +#define NPM2100_GPIO_CONFIG 0x80U +#define NPM2100_GPIO_USAGE 0x83U +#define NPM2100_GPIO_OUTPUT 0x86U +#define NPM2100_GPIO_READ 0x89U + +#define NPM2100_GPIO_PINS 2U + +#define NPM2100_GPIO_CONFIG_INPUT 0x01U +#define NPM2100_GPIO_CONFIG_OUTPUT 0x02U +#define NPM2100_GPIO_CONFIG_OPENDRAIN 0x04U +#define NPM2100_GPIO_CONFIG_PULLDOWN 0x08U +#define NPM2100_GPIO_CONFIG_PULLUP 0x10U +#define NPM2100_GPIO_CONFIG_DRIVE 0x20U +#define NPM2100_GPIO_CONFIG_DEBOUNCE 0x40U + +struct gpio_npm2100_config { + struct gpio_driver_config common; + struct i2c_dt_spec i2c; +}; + +struct gpio_npm2100_data { + struct gpio_driver_data common; +}; + +static int gpio_npm2100_port_get_raw(const struct device *dev, uint32_t *value) +{ + const struct gpio_npm2100_config *config = dev->config; + uint8_t data; + int ret; + + ret = i2c_reg_read_byte_dt(&config->i2c, NPM2100_GPIO_READ, &data); + if (ret < 0) { + return ret; + } + + *value = data; + + return 0; +} + +static int gpio_npm2100_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask, + gpio_port_value_t value) +{ + const struct gpio_npm2100_config *config = dev->config; + int ret = 0; + + for (size_t idx = 0; idx < NPM2100_GPIO_PINS; idx++) { + if ((mask & BIT(idx)) != 0U) { + i2c_reg_write_byte_dt(&config->i2c, NPM2100_GPIO_OUTPUT + idx, + !!(value & BIT(idx))); + if (ret != 0U) { + return ret; + } + } + } + + return ret; +} + +static int gpio_npm2100_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + return gpio_npm2100_port_set_masked_raw(dev, pins, pins); +} + +static int gpio_npm2100_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + return gpio_npm2100_port_set_masked_raw(dev, pins, 0U); +} + +static inline int gpio_npm2100_configure(const struct device *dev, gpio_pin_t pin, + gpio_flags_t flags) +{ + const struct gpio_npm2100_config *config = dev->config; + uint8_t reg = 0U; + + if (k_is_in_isr()) { + return -EWOULDBLOCK; + } + + if (pin >= NPM2100_GPIO_PINS) { + return -EINVAL; + } + + /* Set initial state if defined */ + if ((flags & (GPIO_OUTPUT_INIT_LOW | GPIO_OUTPUT_INIT_HIGH)) != 0U) { + int ret = i2c_reg_write_byte_dt(&config->i2c, NPM2100_GPIO_OUTPUT + pin, + !!(flags & GPIO_OUTPUT_INIT_HIGH)); + if (ret < 0) { + return ret; + } + } + + /* Set pin configuration */ + if ((flags & GPIO_INPUT) != 0U) { + reg |= NPM2100_GPIO_CONFIG_INPUT; + } + if ((flags & GPIO_OUTPUT) != 0U) { + reg |= NPM2100_GPIO_CONFIG_OUTPUT; + } + if ((flags & GPIO_SINGLE_ENDED) != 0U) { + reg |= NPM2100_GPIO_CONFIG_OPENDRAIN; + } + if ((flags & GPIO_PULL_UP) != 0U) { + reg |= NPM2100_GPIO_CONFIG_PULLUP; + } + if ((flags & GPIO_PULL_DOWN) != 0U) { + reg |= NPM2100_GPIO_CONFIG_PULLDOWN; + } + if ((flags & NPM2100_GPIO_DRIVE_HIGH) != 0U) { + reg |= NPM2100_GPIO_CONFIG_DRIVE; + } + if ((flags & NPM2100_GPIO_DEBOUNCE_ON) != 0U) { + reg |= NPM2100_GPIO_CONFIG_DEBOUNCE; + } + + return i2c_reg_write_byte_dt(&config->i2c, NPM2100_GPIO_CONFIG + pin, reg); +} + +static int gpio_npm2100_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins) +{ + int ret; + uint32_t value; + + ret = gpio_npm2100_port_get_raw(dev, &value); + if (ret < 0) { + return ret; + } + + return gpio_npm2100_port_set_masked_raw(dev, pins, ~value); +} + +static DEVICE_API(gpio, gpio_npm2100_api) = { + .pin_configure = gpio_npm2100_configure, + .port_get_raw = gpio_npm2100_port_get_raw, + .port_set_masked_raw = gpio_npm2100_port_set_masked_raw, + .port_set_bits_raw = gpio_npm2100_port_set_bits_raw, + .port_clear_bits_raw = gpio_npm2100_port_clear_bits_raw, + .port_toggle_bits = gpio_npm2100_port_toggle_bits, +}; + +static int gpio_npm2100_init(const struct device *dev) +{ + const struct gpio_npm2100_config *config = dev->config; + + if (!i2c_is_ready_dt(&config->i2c)) { + return -ENODEV; + } + + return 0; +} + +#define GPIO_NPM2100_DEFINE(n) \ + static const struct gpio_npm2100_config gpio_npm2100_config##n = { \ + .common = \ + { \ + .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \ + }, \ + .i2c = I2C_DT_SPEC_GET(DT_INST_PARENT(n))}; \ + \ + static struct gpio_npm2100_data gpio_npm2100_data##n; \ + \ + DEVICE_DT_INST_DEFINE(n, &gpio_npm2100_init, NULL, &gpio_npm2100_data##n, \ + &gpio_npm2100_config##n, POST_KERNEL, \ + CONFIG_GPIO_NPM2100_INIT_PRIORITY, &gpio_npm2100_api); + +DT_INST_FOREACH_STATUS_OKAY(GPIO_NPM2100_DEFINE) diff --git a/dts/bindings/gpio/nordic,npm2100-gpio.yaml b/dts/bindings/gpio/nordic,npm2100-gpio.yaml new file mode 100644 index 00000000000..bb9eb015d03 --- /dev/null +++ b/dts/bindings/gpio/nordic,npm2100-gpio.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: nPM2100 GPIO Controller + +compatible: "nordic,npm2100-gpio" + +include: gpio-controller.yaml + +gpio-cells: + - pin + - flags diff --git a/include/zephyr/dt-bindings/gpio/nordic-npm2100-gpio.h b/include/zephyr/dt-bindings/gpio/nordic-npm2100-gpio.h new file mode 100644 index 00000000000..8173c128d7d --- /dev/null +++ b/include/zephyr/dt-bindings/gpio/nordic-npm2100-gpio.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_NORDIC_NPM2100_GPIO_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_NORDIC_NPM2100_GPIO_H_ + +/** + * @brief nPM2100-specific GPIO Flags + * @defgroup gpio_interface_npm2100 nPM2100-specific GPIO Flags + * + * The drive flags are encoded in the 8 upper bits of @ref gpio_dt_flags_t as + * follows: + * + * - Bit 8: Drive strength (0=1mA, 1=6mA) + * - Bit 9: Debounce (0=OFF, 1=ON) + * + * @ingroup gpio_interface + * @{ + */ + +/** + * @name nPM2100 GPIO drive strength flags + * @brief nPM2100 GPIO drive strength flags + * @{ + */ + +/** @cond INTERNAL_HIDDEN */ +/** Drive mode field mask */ +#define NPM2100_GPIO_DRIVE_MSK 0x0100U +/** @endcond */ + +/** Normal drive */ +#define NPM2100_GPIO_DRIVE_NORMAL (0U << 8U) +/** High drive */ +#define NPM2100_GPIO_DRIVE_HIGH (1U << 8U) + +/** @} */ + +/** + * @name nPM2100 GPIO debounce flags + * @brief nPM2100 GPIO debounce flags + * @{ + */ + +/** @cond INTERNAL_HIDDEN */ +/** Debounce field mask */ +#define NPM2100_GPIO_DEBOUNCE_MSK 0x0200U +/** @endcond */ + +/** Normal drive */ +#define NPM2100_GPIO_DEBOUNCE_OFF (0U << 9U) +/** High drive */ +#define NPM2100_GPIO_DEBOUNCE_ON (1U << 9U) + +/** @} */ + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_NORDIC_NPM2100_GPIO_H_ */ diff --git a/tests/drivers/build_all/gpio/app.overlay b/tests/drivers/build_all/gpio/app.overlay index 9bdf45849e0..ac6b71eb1e3 100644 --- a/tests/drivers/build_all/gpio/app.overlay +++ b/tests/drivers/build_all/gpio/app.overlay @@ -338,9 +338,9 @@ }; }; - it8801_mfd: it8801@38 { + it8801_mfd: it8801@14 { compatible = "ite,it8801-mfd"; - reg = <0x38>; + reg = <0x14>; irq-gpios = <&test_gpio 1 0>; #address-cells = <1>; #size-cells = <1>; @@ -385,6 +385,18 @@ }; }; + test_i2c_npm2100: pmic@15 { + compatible = "nordic,npm2100"; + reg = <0x15>; + + npm2100_gpio: gpio-controller { + compatible = "nordic,npm2100-gpio"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <2>; + }; + }; + }; nct3807_alert_1 {