diff --git a/boards/nuvoton/npcm400f_evb/npcm400f_evb_defconfig b/boards/nuvoton/npcm400f_evb/npcm400f_evb_defconfig index 051da2924c497a..1f751b41fc082a 100644 --- a/boards/nuvoton/npcm400f_evb/npcm400f_evb_defconfig +++ b/boards/nuvoton/npcm400f_evb/npcm400f_evb_defconfig @@ -25,3 +25,7 @@ CONFIG_SERIAL=n # Console Driver CONFIG_CONSOLE=n CONFIG_UART_CONSOLE=n + +# GPIO Driver +CONFIG_GPIO=y +CONFIG_GPIO_NPCM=y diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index 787a10d7dd5d41..38d200f750e286 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -52,6 +52,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_NCT38XX gpio_nct38xx.c) zephyr_library_sources_ifdef(CONFIG_GPIO_NCT38XX gpio_nct38xx_port.c) 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_NPCM gpio_npcm.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_NPM6001 gpio_npm6001.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 9ce2b7f5859f96..7c967c878cb977 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -138,6 +138,7 @@ source "drivers/gpio/Kconfig.mcux_rgpio" source "drivers/gpio/Kconfig.mmio32" source "drivers/gpio/Kconfig.nct38xx" source "drivers/gpio/Kconfig.neorv32" +source "drivers/gpio/Kconfig.npcm" source "drivers/gpio/Kconfig.npcx" source "drivers/gpio/Kconfig.npm1300" source "drivers/gpio/Kconfig.npm6001" diff --git a/drivers/gpio/Kconfig.npcm b/drivers/gpio/Kconfig.npcm new file mode 100644 index 00000000000000..6893ee4387a4d4 --- /dev/null +++ b/drivers/gpio/Kconfig.npcm @@ -0,0 +1,13 @@ +# NPCX GPIO driver configuration options + +# Copyright (c) 2024 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_NPCM + bool "Nuvoton NPCM enhance Super I/O (eSIO) gpio driver" + default y + depends on DT_HAS_NUVOTON_NPCM_GPIO_ENABLED + help + This option enables the GPIO driver for NPCM family of + processors. + Say y if you wish to use serial port on NPCM MCU. diff --git a/drivers/gpio/gpio_npcm.c b/drivers/gpio/gpio_npcm.c new file mode 100644 index 00000000000000..e35520ac073bb0 --- /dev/null +++ b/drivers/gpio/gpio_npcm.c @@ -0,0 +1,430 @@ +/* + * Copyright (c) 2024 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nuvoton_npcm_gpio + +#include +#include +#include +#include + +#include +#include "soc_gpio.h" +#include "soc_miwu.h" + +#include +LOG_MODULE_REGISTER(gpio_npcm, LOG_LEVEL_ERR); + +/* GPIO module instances */ +#define NPCM_GPIO_DEV(inst) DEVICE_DT_INST_GET(inst), +static const struct device *gpio_devs[] = { + DT_INST_FOREACH_STATUS_OKAY(NPCM_GPIO_DEV) +}; + +/* Driver config */ +struct gpio_npcm_config { + /* gpio_driver_config needs to be first */ + struct gpio_driver_config common; + /* GPIO controller base address */ + uintptr_t base; + /* IO port */ + int port; + /* Mapping table between gpio bits and wui */ + struct npcm_wui wui_maps[]; +}; + +/* Driver data */ +struct gpio_npcm_data { + /* gpio_driver_data needs to be first */ + struct gpio_driver_data common; +}; + +struct npcm_scfg_config { + /* scfg device base address */ + uintptr_t base_scfg; +}; + +static const struct npcm_scfg_config npcm_scfg_cfg = { + .base_scfg = DT_REG_ADDR_BY_NAME(DT_NODELABEL(scfg), scfg), +}; + +/* Driver convenience defines */ +#define HAL_INSTANCE(dev) \ + ((struct gpio_reg *)((const struct gpio_npcm_config *)(dev)->config)->base) + +#define HAL_SFCG_INST() (struct scfg_reg *)(npcm_scfg_cfg.base_scfg) + +/* Platform specific GPIO functions */ +const struct device *npcm_get_gpio_dev(int port) +{ + if (port >= ARRAY_SIZE(gpio_devs)) + return NULL; + + return gpio_devs[port]; +} + +#ifdef CONFIG_NPCM_MIWU +void npcm_gpio_enable_io_pads(const struct device *dev, int pin) +{ + const struct gpio_npcm_config *const config = dev->config; + const struct npcm_wui *io_wui = &config->wui_maps[pin]; + + if (io_wui->table == NPCM_MIWU_TABLE_NONE) { + LOG_ERR("Cannot enable GPIO(%x, %d) pad", config->port, pin); + return; + } + + /* + * If this pin is configurred as a GPIO interrupt source, do not + * implement bypass. Or ec cannot wake up via this event. + */ + if (pin < NPCM_GPIO_PORT_PIN_NUM && !npcm_miwu_irq_get_state(io_wui)) { + npcm_miwu_io_enable(io_wui); + } +} + +void npcm_gpio_disable_io_pads(const struct device *dev, int pin) +{ + const struct gpio_npcm_config *const config = dev->config; + const struct npcm_wui *io_wui = &config->wui_maps[pin]; + + if (io_wui->table == NPCM_MIWU_TABLE_NONE) { + LOG_ERR("Cannot enable GPIO(%x, %d) pad", config->port, pin); + return; + } + + /* + * If this pin is configurred as a GPIO interrupt source, do not + * implement bypass. Or ec cannot wake up via this event. + */ + if (pin < NPCM_GPIO_PORT_PIN_NUM && !npcm_miwu_irq_get_state(io_wui)) { + npcm_miwu_io_disable(io_wui); + } +} +#else +void npcm_gpio_enable_io_pads(const struct device *dev, int pin) +{ +} +void npcm_gpio_disable_io_pads(const struct device *dev, int pin) +{ +} +#endif + +/* GPIO api functions */ +static int gpio_npcm_config(const struct device *dev, + gpio_pin_t pin, gpio_flags_t flags) +{ + struct gpio_reg *const inst = HAL_INSTANCE(dev); + struct scfg_reg *inst_scfg = HAL_SFCG_INST(); + uint32_t mask = BIT(pin); + + /* Don't support simultaneous in/out mode */ + if (((flags & GPIO_INPUT) != 0) && ((flags & GPIO_OUTPUT) != 0)) { + return -ENOTSUP; + } + + /* Don't support "open source" mode */ + if (((flags & GPIO_SINGLE_ENDED) != 0) && + ((flags & GPIO_LINE_OPEN_DRAIN) == 0)) { + return -ENOTSUP; + } + + /* + * Configure pin as input, if requested. Output is configured only + * after setting all other attributes, so as not to create a + * temporary incorrect logic state 0:input 1:output + */ + if ((flags & GPIO_OUTPUT) == 0) + inst->PDIR &= ~mask; + + /* Select open drain 0:push-pull 1:open-drain */ + if ((flags & GPIO_OPEN_DRAIN) != 0) + inst->PTYPE |= mask; + else + inst->PTYPE &= ~mask; + + /* Select opend drain with pull up need enable GPIO_PULL_EN */ + if (((flags & GPIO_OPEN_DRAIN) != 0) && + ((flags & GPIO_PULL_UP) != 0)) { + inst_scfg->DEVALTCX |= BIT(NPCM_DEVALTCX_GPIO_PULL_EN); + } + + /* Select pull-up/down of GPIO 0:pull-up 1:pull-down */ + if ((flags & GPIO_PULL_UP) != 0) { + inst->PPUD &= ~mask; + inst->PPULL |= mask; + } else if ((flags & GPIO_PULL_DOWN) != 0) { + inst->PPUD |= mask; + inst->PPULL |= mask; + } else { + /* disable pull down/up */ + inst->PPULL &= ~mask; + } + + /* Set level 0:low 1:high */ + if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) + inst->PDOUT |= mask; + else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) + inst->PDOUT &= ~mask; + + /* Configure pin as output, if requested 0:input 1:output */ + if ((flags & GPIO_OUTPUT) != 0) + inst->PDIR |= mask; + + return 0; +} + +#ifdef CONFIG_GPIO_GET_CONFIG +static int gpio_npcm_pin_get_config(const struct device *port, gpio_pin_t pin, + gpio_flags_t *out_flags) +{ + const struct gpio_npcm_config *const config = port->config; + struct gpio_reg *const inst = HAL_INSTANCE(port); + uint32_t mask = BIT(pin); + gpio_flags_t flags = 0; + + /* 0:input 1:output */ + if (inst->PDIR & mask) { + flags |= GPIO_OUTPUT; + + /* 0:push-pull 1:open-drain */ + if (inst->PTYPE & mask) { + flags |= GPIO_OPEN_DRAIN; + } + + /* 0:low 1:high */ + if (inst->PDOUT & mask) { + flags |= GPIO_OUTPUT_HIGH; + } else { + flags |= GPIO_OUTPUT_LOW; + } + } else { + flags |= GPIO_INPUT; + + /* 0:disabled 1:enabled pull */ + if (inst->PPULL & mask) { + /* 0:pull-up 1:pull-down */ + if (inst->PPUD & mask) { + flags |= GPIO_PULL_DOWN; + } else { + flags |= GPIO_PULL_UP; + } + } + } + + *out_flags = flags; + + return 0; +} +#endif + +static int gpio_npcm_port_get_raw(const struct device *dev, + gpio_port_value_t *value) +{ + struct gpio_reg *const inst = HAL_INSTANCE(dev); + + /* Get raw bits of GPIO input registers */ + *value = inst->PDIN; + + return 0; +} + +static int gpio_npcm_port_set_masked_raw(const struct device *dev, + gpio_port_pins_t mask, + gpio_port_value_t value) +{ + struct gpio_reg *const inst = HAL_INSTANCE(dev); + uint8_t out = inst->PDOUT; + + inst->PDOUT = ((out & ~mask) | (value & mask)); + + return 0; +} + +static int gpio_npcm_port_set_bits_raw(const struct device *dev, + gpio_port_value_t mask) +{ + struct gpio_reg *const inst = HAL_INSTANCE(dev); + + /* Set raw bits of GPIO output registers */ + inst->PDOUT |= mask; + + return 0; +} + +static int gpio_npcm_port_clear_bits_raw(const struct device *dev, + gpio_port_value_t mask) +{ + struct gpio_reg *const inst = HAL_INSTANCE(dev); + + /* Clear raw bits of GPIO output registers */ + inst->PDOUT &= ~mask; + + return 0; +} + +static int gpio_npcm_port_toggle_bits(const struct device *dev, + gpio_port_value_t mask) +{ + struct gpio_reg *const inst = HAL_INSTANCE(dev); + + /* Toggle raw bits of GPIO output registers */ + inst->PDOUT ^= mask; + + return 0; +} + +#ifdef CONFIG_NPCM_MIWU +static int gpio_npcm_pin_interrupt_configure(const struct device *dev, + gpio_pin_t pin, + enum gpio_int_mode mode, + enum gpio_int_trig trig) +{ + const struct gpio_npcm_config *const config = dev->config; + + if (config->wui_maps[pin].table == NPCM_MIWU_TABLE_NONE) { + LOG_ERR("Cannot configure GPIO(%x, %d)", config->port, pin); + return -EINVAL; + } + + LOG_DBG("pin_int_conf (%d, %d) match (%d, %d, %d)!!!", + config->port, pin, config->wui_maps[pin].table, + config->wui_maps[pin].group, + config->wui_maps[pin].bit); + + /* Disable irq of wake-up input io-pads before configuring them */ + npcm_miwu_irq_disable(&config->wui_maps[pin]); + + /* Configure and enable interrupt? */ + if (mode != GPIO_INT_MODE_DISABLED) { + enum miwu_int_mode miwu_mode; + enum miwu_int_trig miwu_trig; + int ret = 0; + + /* Determine interrupt is level or edge mode? */ + if (mode == GPIO_INT_MODE_EDGE) { + miwu_mode = NPCM_MIWU_MODE_EDGE; + } else { + miwu_mode = NPCM_MIWU_MODE_LEVEL; + } + + /* Determine trigger mode is low, high or both? */ + if (trig == GPIO_INT_TRIG_LOW) { + miwu_trig = NPCM_MIWU_TRIG_LOW; + } else if (trig == GPIO_INT_TRIG_HIGH) { + miwu_trig = NPCM_MIWU_TRIG_HIGH; + } else if (trig == GPIO_INT_TRIG_BOTH) { + miwu_trig = NPCM_MIWU_TRIG_BOTH; + } else { + LOG_ERR("Invalid interrupt trigger type %d", trig); + return -EINVAL; + } + + /* Call MIWU routine to setup interrupt configuration */ + ret = npcm_miwu_interrupt_configure(&config->wui_maps[pin], + miwu_mode, miwu_trig); + if (ret != 0) { + LOG_ERR("Configure MIWU interrupt failed"); + return ret; + } + + /* Enable it after configuration is completed */ + npcm_miwu_irq_enable(&config->wui_maps[pin]); + } + + return 0; +} +#else +static int gpio_npcm_pin_interrupt_configure(const struct device *dev, + gpio_pin_t pin, + enum gpio_int_mode mode, + enum gpio_int_trig trig) +{ + return -EINVAL; +} +#endif + + +#ifdef CONFIG_NPCM_MIWU +static int gpio_npcm_manage_callback(const struct device *dev, + struct gpio_callback *callback, bool set) +{ + const struct gpio_npcm_config *const config = dev->config; + struct miwu_io_callback *miwu_cb = (struct miwu_io_callback *)callback; + int pin = find_lsb_set(callback->pin_mask) - 1; + + /* pin_mask should not be zero */ + if (pin < 0) { + return -EINVAL; + } + + /* Has the IO pin valid MIWU input source? */ + if (config->wui_maps[pin].table == NPCM_MIWU_TABLE_NONE) { + LOG_ERR("Cannot manage GPIO(%x, %d) callback!", config->port, + pin); + return -EINVAL; + } + + /* Initialize WUI information in unused bits field */ + npcm_miwu_init_gpio_callback(miwu_cb, &config->wui_maps[pin], + config->port); + + /* Insert or remove a IO callback which being called in MIWU ISRs */ + return npcm_miwu_manage_gpio_callback(miwu_cb, set); +} +#else +static int gpio_npcm_manage_callback(const struct device *dev, + struct gpio_callback *callback, bool set) +{ + return -EINVAL; +} +#endif + +/* GPIO driver registration */ +static const struct gpio_driver_api gpio_npcm_driver = { + .pin_configure = gpio_npcm_config, +#ifdef CONFIG_GPIO_GET_CONFIG + .pin_get_config = gpio_npcm_pin_get_config, +#endif + .port_get_raw = gpio_npcm_port_get_raw, + .port_set_masked_raw = gpio_npcm_port_set_masked_raw, + .port_set_bits_raw = gpio_npcm_port_set_bits_raw, + .port_clear_bits_raw = gpio_npcm_port_clear_bits_raw, + .port_toggle_bits = gpio_npcm_port_toggle_bits, + .pin_interrupt_configure = gpio_npcm_pin_interrupt_configure, + .manage_callback = gpio_npcm_manage_callback, +}; + +int gpio_npcm_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + return 0; +} + +#define NPCM_GPIO_DEVICE_INIT(inst) \ + static const struct gpio_npcm_config gpio_npcm_cfg_##inst = { \ + .common = { \ + .port_pin_mask = \ + GPIO_PORT_PIN_MASK_FROM_NGPIOS(NPCM_GPIO_PORT_PIN_NUM), \ + }, \ + .base = DT_INST_REG_ADDR(inst), \ + .port = inst, \ + .wui_maps = NPCM_DT_WUI_ITEMS_LIST(inst), \ + }; \ + BUILD_ASSERT(NPCM_DT_WUI_ITEMS_LEN(inst) == NPCM_GPIO_PORT_PIN_NUM, \ + "size of prop. wui-maps must equal to pin number!"); \ + static struct gpio_npcm_data gpio_npcm_data_##inst; \ + \ + DEVICE_DT_INST_DEFINE(inst, \ + gpio_npcm_init, \ + NULL, \ + &gpio_npcm_data_##inst, \ + &gpio_npcm_cfg_##inst, \ + PRE_KERNEL_1, \ + CONFIG_GPIO_INIT_PRIORITY, \ + &gpio_npcm_driver); +DT_INST_FOREACH_STATUS_OKAY(NPCM_GPIO_DEVICE_INIT) diff --git a/dts/arm/nuvoton/npcm/npcm-miwus-wui-map.dtsi b/dts/arm/nuvoton/npcm/npcm-miwus-wui-map.dtsi new file mode 100644 index 00000000000000..28ba917a41df0a --- /dev/null +++ b/dts/arm/nuvoton/npcm/npcm-miwus-wui-map.dtsi @@ -0,0 +1,555 @@ +/* + * Copyright (c) 2024 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + /* Mapping between MIWU wui bits and source device */ + npcm_miwus_wui { + compatible = "nuvoton,npcm-miwu-wui-map"; + + /* MIWU table 0 */ + /* MIWU group A */ + wui_io00: wui0-1-0 { + miwus = <&miwu0 0 0>; /* GPIO00 */ + }; + wui_io01: wui0-1-1 { + miwus = <&miwu0 0 1>; /* GPIO01 */ + }; + wui_io02: wui0-1-2 { + miwus = <&miwu0 0 2>; /* GPIO02 */ + }; + wui_io03: wui0-1-3 { + miwus = <&miwu0 0 3>; /* GPIO03 */ + }; + wui_io04: wui0-1-4 { + miwus = <&miwu0 0 4>; /* GPIO04 */ + }; + wui_io05: wui0-1-5 { + miwus = <&miwu0 0 5>; /* GPIO05 */ + }; + wui_io06: wui0-1-6 { + miwus = <&miwu0 0 6>; /* GPIO06 */ + }; + wui_io07: wui0-1-7 { + miwus = <&miwu0 0 7>; /* GPIO07 */ + }; + + /* MIWU group B */ + wui_io10: wui0-2-0 { + miwus = <&miwu0 1 0>; /* GPIO10 */ + }; + wui_io11: wui0-2-1 { + miwus = <&miwu0 1 1>; /* GPIO11 */ + }; + wui_io12: wui0-2-2 { + miwus = <&miwu0 1 2>; /* GPIO12 */ + }; + wui_io13: wui0-2-3 { + miwus = <&miwu0 1 3>; /* GPIO13 */ + }; + wui_io14: wui0-2-4 { + miwus = <&miwu0 1 4>; /* GPIO14 */ + }; + wui_io15: wui0-2-5 { + miwus = <&miwu0 1 5>; /* GPIO15 */ + }; + wui_io16: wui0-2-6 { + miwus = <&miwu0 1 6>; /* GPIO16 */ + }; + wui_io17: wui0-2-7 { + miwus = <&miwu0 1 7>; /* GPIO17 */ + }; + + /* MIWU group C */ + wui_io20: wui0-3-0 { + miwus = <&miwu0 2 0>; /* GPIO20 */ + }; + wui_io21: wui0-3-1 { + miwus = <&miwu0 2 1>; /* GPIO21 */ + }; + wui_io22: wui0-3-2 { + miwus = <&miwu0 2 2>; /* GPIO22 */ + }; + wui_io23: wui0-3-3 { + miwus = <&miwu0 2 3>; /* GPIO23 */ + }; + wui_io24: wui0-3-4 { + miwus = <&miwu0 2 4>; /* GPIO24 */ + }; + wui_io25: wui0-3-5 { + miwus = <&miwu0 2 5>; /* GPIO25 */ + }; + wui_io26: wui0-3-6 { + miwus = <&miwu0 2 6>; /* GPIO26 */ + }; + wui_io27: wui0-3-7 { + miwus = <&miwu0 2 7>; /* GPIO27 */ + }; + + /* MIWU group D */ + wui_io30: wui0-4-0 { + miwus = <&miwu0 3 0>; /* GPIO30 */ + }; + wui_io31: wui0-4-1 { + miwus = <&miwu0 3 1>; /* GPIO31 */ + }; + wui_io32: wui0-4-2 { + miwus = <&miwu0 3 2>; /* GPIO32 */ + }; + wui_io33: wui0-4-3 { + miwus = <&miwu0 3 3>; /* GPIO33 */ + }; + wui_io34: wui0-4-4 { + miwus = <&miwu0 3 4>; /* GPIO34 */ + }; + wui_io35: wui0-4-5 { + miwus = <&miwu0 3 5>; /* GPIO35 */ + }; + wui_io36: wui0-4-6 { + miwus = <&miwu0 3 6>; /* GPIO36 */ + }; + wui_io37: wui0-4-7 { + miwus = <&miwu0 3 7>; /* GPIO37 */ + }; + + /* MIWU group E */ + wui_io40: wui0-5-0 { + miwus = <&miwu0 4 0>; /* GPIO40 */ + }; + wui_io41: wui0-5-1 { + miwus = <&miwu0 4 1>; /* GPIO41 */ + }; + wui_io42: wui0-5-2 { + miwus = <&miwu0 4 2>; /* GPIO42 */ + }; + wui_io43: wui0-5-3 { + miwus = <&miwu0 4 3>; /* GPIO43 */ + }; + wui_io44: wui0-5-4 { + miwus = <&miwu0 4 4>; /* GPIO44 */ + }; + wui_io45: wui0-5-5 { + miwus = <&miwu0 4 5>; /* GPIO45 */ + }; + wui_io46: wui0-5-6 { + miwus = <&miwu0 4 6>; /* GPIO46 */ + }; + wui_io47: wui0-5-7 { + miwus = <&miwu0 4 7>; /* GPIO47 */ + }; + + /* MIWU group F */ + wui_io50: wui0-6-0 { + miwus = <&miwu0 5 0>; /* GPIO50 */ + }; + wui_io51: wui0-6-1 { + miwus = <&miwu0 5 1>; /* GPIO51 */ + }; + wui_io52: wui0-6-2 { + miwus = <&miwu0 5 2>; /* GPIO52 */ + }; + wui_io53: wui0-6-3 { + miwus = <&miwu0 5 3>; /* GPIO53 */ + }; + wui_io54: wui0-6-4 { + miwus = <&miwu0 5 4>; /* GPIO54 */ + }; + wui_io55: wui0-6-5 { + miwus = <&miwu0 5 5>; /* GPIO55 */ + }; + wui_io56: wui0-6-6 { + miwus = <&miwu0 5 6>; /* GPIO56 */ + }; + wui_io57: wui0-6-7 { + miwus = <&miwu0 5 7>; /* GPIO57 */ + }; + + /* MIWU group G */ + wui_io60: wui0-7-0 { + miwus = <&miwu0 6 0>; /* GPIO60 */ + }; + wui_io61: wui0-7-1 { + miwus = <&miwu0 6 1>; /* GPIO61 */ + }; + wui_io62: wui0-7-2 { + miwus = <&miwu0 6 2>; /* GPIO62 */ + }; + wui_io63: wui0-7-3 { + miwus = <&miwu0 6 3>; /* GPIO63 */ + }; + wui_io64: wui0-7-4 { + miwus = <&miwu0 6 4>; /* GPIO64 */ + }; + wui_io65: wui0-7-5 { + miwus = <&miwu0 6 5>; /* GPIO65 */ + }; + wui_io66: wui0-7-6 { + miwus = <&miwu0 6 6>; /* GPIO66 */ + }; + wui_io67: wui0-7-7 { + miwus = <&miwu0 6 7>; /* GPIO67 */ + }; + + /* MIWU group H */ + wui_io70: wui0-8-0 { + miwus = <&miwu0 7 0>; /* GPIO70 */ + }; + wui_io71: wui0-8-1 { + miwus = <&miwu0 7 1>; /* GPIO71 */ + }; + wui_io72: wui0-8-2 { + miwus = <&miwu0 7 2>; /* GPIO72 */ + }; + wui_io73: wui0-8-3 { + miwus = <&miwu0 7 3>; /* GPIO73 */ + }; + wui_io74: wui0-8-4 { + miwus = <&miwu0 7 4>; /* GPIO74 */ + }; + wui_io75: wui0-8-5 { + miwus = <&miwu0 7 5>; /* GPIO75 */ + }; + wui_io76: wui0-8-6 { + miwus = <&miwu0 7 6>; /* GPIO76 */ + }; + wui_io77: wui0-8-7 { + miwus = <&miwu0 7 7>; /* GPIO77 */ + }; + + /* MIWU table 1 */ + /* MIWU group A */ + wui_io80: wui1-1-0 { + miwus = <&miwu1 0 0>; /* GPIO80 */ + }; + wui_io81: wui1-1-1 { + miwus = <&miwu1 0 1>; /* GPIO81 */ + }; + wui_io82: wui1-1-2 { + miwus = <&miwu1 0 2>; /* GPIO82 */ + }; + wui_io83: wui1-1-3 { + miwus = <&miwu1 0 3>; /* GPIO83 */ + }; + wui_io84: wui1-1-4 { + miwus = <&miwu1 0 4>; /* GPIO84 */ + }; + wui_io85: wui1-1-5 { + miwus = <&miwu1 0 5>; /* GPIO85 */ + }; + wui_io86: wui1-1-6 { + miwus = <&miwu1 0 6>; /* GPIO86 */ + }; + wui_io87: wui1-1-7 { + miwus = <&miwu1 0 7>; /* GPIO87 */ + }; + + /* MIWU group B */ + wui_io90: wui1-2-0 { + miwus = <&miwu1 1 0>; /* GPIO90 */ + }; + wui_io91: wui1-2-1 { + miwus = <&miwu1 1 1>; /* GPIO91 */ + }; + wui_io92: wui1-2-2 { + miwus = <&miwu1 1 2>; /* GPIO92 */ + }; + wui_io93: wui1-2-3 { + miwus = <&miwu1 1 3>; /* GPIO93 */ + }; + wui_io94: wui1-2-4 { + miwus = <&miwu1 1 4>; /* GPIO94 */ + }; + wui_io95: wui1-2-5 { + miwus = <&miwu1 1 5>; /* GPIO95 */ + }; + wui_io96: wui1-2-6 { + miwus = <&miwu1 1 6>; /* GPIO96 */ + }; + wui_io97: wui1-2-7 { + miwus = <&miwu1 1 7>; /* GPIO97 */ + }; + + /* MIWU group C */ + wui_ioa0: wui1-3-0 { + miwus = <&miwu1 2 0>; /* GPIOA0 */ + }; + wui_ioa1: wui1-3-1 { + miwus = <&miwu1 2 1>; /* GPIOA1 */ + }; + wui_ioa2: wui1-3-2 { + miwus = <&miwu1 2 2>; /* GPIOA2 */ + }; + wui_ioa3: wui1-3-3 { + miwus = <&miwu1 2 3>; /* GPIOA3 */ + }; + wui_ioa4: wui1-3-4 { + miwus = <&miwu1 2 4>; /* GPIOA4 */ + }; + wui_ioa5: wui1-3-5 { + miwus = <&miwu1 2 5>; /* GPIOA5 */ + }; + wui_ioa6: wui1-3-6 { + miwus = <&miwu1 2 6>; /* GPIOA6 */ + }; + wui_ioa7: wui1-3-7 { + miwus = <&miwu1 2 7>; /* GPIOA7 */ + }; + + /* MIWU group D */ + wui_cdbg: wui1-4-4 { + miwus = <&miwu1 3 4>; /* CDBGPWRUPREQ */ + }; + wui_lpc_ev: wui1-4-5 { + miwus = <&miwu1 3 5>; /* LPC_EV_WKUP */ + }; + wui_host_acc: wui1-4-6 { + miwus = <&miwu1 3 6>; /* HOST_ACC */ + }; + wui_espi_rst: wui1-4-7 { + miwus = <&miwu1 3 7>; /* PLT_RST/ESPI_RST */ + }; + + /* MIWU group E */ + wui_emac: wui1-5-0 { + miwus = <&miwu1 4 0>; /* EMAC */ + }; + wui_mswc: wui1-5-2 { + miwus = <&miwu1 4 2>; /* MSWC */ + }; + wui_t0out: wui1-5-3 { + miwus = <&miwu1 4 3>; /* T0OUT */ + }; + + /* MIWU group F */ + wui_iob0: wui1-6-0 { + miwus = <&miwu1 5 0>; /* GPIOB0 */ + }; + wui_iob1: wui1-6-1 { + miwus = <&miwu1 5 1>; /* GPIOB1 */ + }; + wui_iob2: wui1-6-2 { + miwus = <&miwu1 5 2>; /* GPIOB2 */ + }; + wui_iob3: wui1-6-3 { + miwus = <&miwu1 5 3>; /* GPIOB3 */ + }; + wui_iob4: wui1-6-4 { + miwus = <&miwu1 5 4>; /* GPIOB4 */ + }; + wui_iob5: wui1-6-5 { + miwus = <&miwu1 5 5>; /* GPIOB5 */ + }; + wui_iob6: wui1-6-6 { + miwus = <&miwu1 5 6>; /* GPIOB6 */ + }; + wui_iob7: wui1-6-7 { + miwus = <&miwu1 5 7>; /* GPIOB7 */ + }; + + /* MIWU group G */ + wui_i3c: wui1-7-7 { + miwus = <&miwu1 6 7>; /* I3C1/2 */ + }; + + /* MIWU group H */ + wui_smb1: wui1-8-1 { + miwus = <&miwu1 7 1>; /* SMB1 */ + }; + wui_smb3: wui1-8-3 { + miwus = <&miwu1 7 3>; /* SMB3 */ + }; + wui_smb4: wui1-8-4 { + miwus = <&miwu1 7 4>; /* SMB4 */ + }; + wui_smb5: wui1-8-5 { + miwus = <&miwu1 7 5>; /* SMB5 */ + }; + wui_smb6: wui1-8-6 { + miwus = <&miwu1 7 6>; /* SMB6 */ + }; + wui_rtc: wui1-8-7 { + miwus = <&miwu1 7 7>; /* RTC */ + }; + + /* MIWU table 2 */ + /* MIWU group A */ + /* eSPI VW Events */ + wui_vw_slp_s3: wui2-1-0 { + miwus = <&miwu2 0 0>; /* VW020 SLP_S3_L */ + }; + wui_vw_slp_s4: wui2-1-1 { + miwus = <&miwu2 0 1>; /* VW021 SLP_S4_L */ + }; + wui_vw_slp_s5: wui2-1-2 { + miwus = <&miwu2 0 2>; /* VW022 SLP_S5_L */ + }; + wui_vw_sus_stat: wui2-1-4 { + miwus = <&miwu2 0 4>; /* SUS_STAT_L */ + }; + wui_vw_plt_rst: wui2-1-5 { + miwus = <&miwu2 0 5>; /* PLTRST_L */ + }; + wui_vw_oob_rst_warn: wui2-1-6 { + miwus = <&miwu2 0 6>; /* OOB_RST_WARN */ + }; + + /* MIWU group B */ + wui_vw_host_rst_warn: wui2-2-0 { + miwus = <&miwu2 1 0>; /* HOST_RST_WARN */ + }; + wui_vw_sus_warn: wui2-2-4 { + miwus = <&miwu2 1 4>; /* SUS_WARN_L */ + }; + wui_vw_sus_pwrdn_ack: wui2-2-5 { + miwus = <&miwu2 1 5>; /* SUS_PWRDN_ACK */ + }; + wui_vw_slp_a: wui2-2-7 { + miwus = <&miwu2 1 7>; /* SLP_A_L */ + }; + + /* MIWU group C */ + /* eSPI VW Events */ + wui_vw_slp_lan: wui2-3-0 { + miwus = <&miwu2 2 0>; /* SLP_LAN_L */ + }; + wui_vw_slp_wlan: wui2-3-1 { + miwus = <&miwu2 2 1>; /* SLP_WLAN_L) */ + }; + wui_vw_pch_to_ec_gen_0: wui2-3-4 { + miwus = <&miwu2 2 4>; /* PCH_TO_EC_GENERIC_0 */ + }; + wui_vw_pch_to_ec_gen_1: wui2-3-5 { + miwus = <&miwu2 2 5>; /* PCH_TO_EC_GENERIC_1 */ + }; + wui_vw_pch_to_ec_gen_2: wui2-3-6 { + miwus = <&miwu2 2 6>; /* PCH_TO_EC_GENERIC_2 */ + }; + wui_vw_pch_to_ec_gen_3: wui2-3-7 { + miwus = <&miwu2 2 7>; /* PCH_TO_EC_GENERIC_3 */ + }; + + /* MIWU group D */ + wui_vw_pch_to_ec_gen_4: wui2-4-0 { + miwus = <&miwu2 3 0>; /* PCH_TO_EC_GENERIC_4 */ + }; + wui_vw_pch_to_ec_gen_5: wui2-4-1 { + miwus = <&miwu2 3 1>; /* PCH_TO_EC_GENERIC_5 */ + }; + wui_vw_pch_to_ec_gen_6: wui2-4-2 { + miwus = <&miwu2 3 2>; /* PCH_TO_EC_GENERIC_6 */ + }; + wui_vw_pch_to_ec_gen_7: wui2-4-3 { + miwus = <&miwu2 3 3>; /* PCH_TO_EC_GENERIC_7 */ + }; + wui_vw_host_c10: wui2-4-4 { + miwus = <&miwu2 3 4>; /* HOST_C10 */ + }; + + /* MIWU group E */ + wui_ioc0: wui2-5-0 { + miwus = <&miwu2 4 0>; /* GPIOC0 */ + }; + wui_ioc1: wui2-5-1 { + miwus = <&miwu2 4 1>; /* GPIOC1 */ + }; + wui_ioc2: wui2-5-2 { + miwus = <&miwu2 4 2>; /* GPIOC2 */ + }; + wui_ioc3: wui2-5-3 { + miwus = <&miwu2 4 3>; /* GPIOC3 */ + }; + wui_ioc4: wui2-5-4 { + miwus = <&miwu2 4 4>; /* GPIOC4 */ + }; + wui_ioc5: wui2-5-5 { + miwus = <&miwu2 4 5>; /* GPIOC5 */ + }; + wui_ioc6: wui2-5-6 { + miwus = <&miwu2 4 6>; /* GPIOC6 */ + }; + wui_ioc7: wui2-5-7 { + miwus = <&miwu2 4 7>; /* GPIOC7 */ + }; + + /* MIWU group F */ + wui_iod0: wui2-6-0 { + miwus = <&miwu2 5 0>; /* GPIOD0 */ + }; + wui_iod1: wui2-6-1 { + miwus = <&miwu2 5 1>; /* GPIOD1 */ + }; + wui_iod2: wui2-6-2 { + miwus = <&miwu2 5 2>; /* GPIOD2 */ + }; + wui_iod3: wui2-6-3 { + miwus = <&miwu2 5 3>; /* GPIOD3 */ + }; + wui_iod4: wui2-6-4 { + miwus = <&miwu2 5 4>; /* GPIOD4 */ + }; + wui_iod5: wui2-6-5 { + miwus = <&miwu2 5 5>; /* GPIOD5 */ + }; + wui_iod6: wui2-6-6 { + miwus = <&miwu2 5 6>; /* GPIOD6 */ + }; + wui_iod7: wui2-6-7 { + miwus = <&miwu2 5 7>; /* GPIOD7 */ + }; + + /* MIWU group G */ + wui_ioe0: wui2-7-0 { + miwus = <&miwu2 6 0>; /* GPIOE0 */ + }; + wui_ioe1: wui2-7-1 { + miwus = <&miwu2 6 1>; /* GPIOE1 */ + }; + wui_ioe2: wui2-7-2 { + miwus = <&miwu2 6 2>; /* GPIOE2 */ + }; + wui_ioe3: wui2-7-3 { + miwus = <&miwu2 6 3>; /* GPIOE3 */ + }; + wui_ioe4: wui2-7-4 { + miwus = <&miwu2 6 4>; /* GPIOE4 */ + }; + wui_ioe5: wui2-7-5 { + miwus = <&miwu2 6 5>; /* GPIOE5 */ + }; + wui_ioe6: wui2-7-6 { + miwus = <&miwu2 6 6>; /* GPIOE6 */ + }; + + /* MIWU group H */ + wui_iof0: wui2-8-0 { + miwus = <&miwu2 7 0>; /* GPIOF0 */ + }; + wui_iof1: wui2-8-1 { + miwus = <&miwu2 7 1>; /* GPIOF1 */ + }; + wui_iof2: wui2-8-2 { + miwus = <&miwu2 7 2>; /* GPIOF2 */ + }; + wui_iof3: wui2-8-3 { + miwus = <&miwu2 7 3>; /* GPIOF3 */ + }; + wui_vcc: wui2-8-7 { + miwus = <&miwu2 7 7>; /* VCC */ + }; + + /* Pseudo wui item means no mapping between source and wui */ + wui_none: wui-pseudo { + miwus = <&miwu_none 7 7>; + }; + }; + + /* Pseudo MIWU device to present no mapping relationship */ + miwu_none: miwu-pseudo { + compatible = "nuvoton,npcm-miwu"; + index = <3>; + #miwu-cells = <2>; + status = "disabled"; + }; +}; diff --git a/dts/arm/nuvoton/npcm/npcm.dtsi b/dts/arm/nuvoton/npcm/npcm.dtsi index 7e47f87ff3e334..5d6b81f5ca2336 100644 --- a/dts/arm/nuvoton/npcm/npcm.dtsi +++ b/dts/arm/nuvoton/npcm/npcm.dtsi @@ -69,6 +69,155 @@ reg = <0x4000c00a 0x4>; reg-io-width = <2>; }; + + miwu0: miwu@400bb000 { + compatible = "nuvoton,npcm-miwu"; + reg = <0x400bb000 0x2000>; + index = <0>; + #miwu-cells = <2>; + }; + + miwu1: miwu@400bd000 { + compatible = "nuvoton,npcm-miwu"; + reg = <0x400bd000 0x2000>; + index = <1>; + #miwu-cells = <2>; + }; + + miwu2: miwu@400bf000 { + compatible = "nuvoton,npcm-miwu"; + reg = <0x400bf000 0x2000>; + index = <2>; + #miwu-cells = <2>; + }; + + gpio0: gpio@40081000 { + compatible = "nuvoton,npcm-gpio"; + reg = <0x40081000 0x2000>; + gpio-controller; + index = <0x0>; + #gpio-cells=<2>; + }; + + gpio1: gpio@40083000 { + compatible = "nuvoton,npcm-gpio"; + reg = <0x40083000 0x2000>; + gpio-controller; + index = <0x1>; + #gpio-cells=<2>; + }; + + gpio2: gpio@40085000 { + compatible = "nuvoton,npcm-gpio"; + reg = <0x40085000 0x2000>; + gpio-controller; + index = <0x2>; + #gpio-cells=<2>; + }; + + gpio3: gpio@40087000 { + compatible = "nuvoton,npcm-gpio"; + reg = <0x40087000 0x2000>; + gpio-controller; + index = <0x3>; + #gpio-cells=<2>; + }; + + gpio4: gpio@40089000 { + compatible = "nuvoton,npcm-gpio"; + reg = <0x40089000 0x2000>; + gpio-controller; + index = <0x4>; + #gpio-cells=<2>; + }; + + gpio5: gpio@4008b000 { + compatible = "nuvoton,npcm-gpio"; + reg = <0x4008b000 0x2000>; + gpio-controller; + index = <0x5>; + #gpio-cells=<2>; + }; + + gpio6: gpio@4008d000 { + compatible = "nuvoton,npcm-gpio"; + reg = <0x4008d000 0x2000>; + gpio-controller; + index = <0x6>; + #gpio-cells=<2>; + }; + + gpio7: gpio@4008f000 { + compatible = "nuvoton,npcm-gpio"; + reg = <0x4008f000 0x2000>; + gpio-controller; + index = <0x7>; + #gpio-cells=<2>; + }; + + gpio8: gpio@40091000 { + compatible = "nuvoton,npcm-gpio"; + reg = <0x40091000 0x2000>; + gpio-controller; + index = <0x8>; + #gpio-cells=<2>; + }; + + gpio9: gpio@40093000 { + compatible = "nuvoton,npcm-gpio"; + reg = <0x40093000 0x2000>; + gpio-controller; + index = <0x9>; + #gpio-cells=<2>; + }; + + gpioa: gpio@40095000 { + compatible = "nuvoton,npcm-gpio"; + reg = <0x40095000 0x2000>; + gpio-controller; + index = <0xA>; + #gpio-cells=<2>; + }; + + gpiob: gpio@40097000 { + compatible = "nuvoton,npcm-gpio"; + reg = <0x40097000 0x2000>; + gpio-controller; + index = <0xB>; + #gpio-cells=<2>; + }; + + gpioc: gpio@40099000 { + compatible = "nuvoton,npcm-gpio"; + reg = <0x40099000 0x2000>; + gpio-controller; + index = <0xC>; + #gpio-cells=<2>; + }; + + gpiod: gpio@4009b000 { + compatible = "nuvoton,npcm-gpio"; + reg = <0x4009b000 0x2000>; + gpio-controller; + index = <0xD>; + #gpio-cells=<2>; + }; + + gpioe: gpio@4009d000 { + compatible = "nuvoton,npcm-gpio"; + reg = <0x4009d000 0x2000>; + gpio-controller; + index = <0xE>; + #gpio-cells=<2>; + }; + + gpiof: gpio@4009f000 { + compatible = "nuvoton,npcm-gpio"; + reg = <0x4009f000 0x2000>; + gpio-controller; + index = <0xF>; + #gpio-cells=<2>; + }; }; soc-id { diff --git a/dts/arm/nuvoton/npcm/npcm4.dtsi b/dts/arm/nuvoton/npcm/npcm4.dtsi index 66cddb070bc59c..a7cb004755e272 100644 --- a/dts/arm/nuvoton/npcm/npcm4.dtsi +++ b/dts/arm/nuvoton/npcm/npcm4.dtsi @@ -6,6 +6,8 @@ /* npcm4 series pinmux mapping table */ #include "npcm4/npcm4-alts-map.dtsi" +/* npcm4 series mapping table between MIWU groups and interrupts */ +#include "npcm4/npcm4-miwus-wui-map.dtsi" /* Device tree declarations of npcm soc family */ #include "npcm.dtsi" @@ -36,6 +38,86 @@ apb2-prescaler = <1>; /* APB2_CLK runs at 96MHz */ apb3-prescaler = <1>; /* APB3_CLK runs at 96MHz */ }; + + gpio0: gpio@40081000 { + wui-maps = <&wui_io00 &wui_io01 &wui_io02 &wui_io03 + &wui_io04 &wui_io05 &wui_io06 &wui_io07>; + }; + + gpio1: gpio@40083000 { + wui-maps = <&wui_io10 &wui_io11 &wui_io12 &wui_io13 + &wui_io14 &wui_io15 &wui_io16 &wui_io17>; + }; + + gpio2: gpio@40085000 { + wui-maps = <&wui_io20 &wui_io21 &wui_io22 &wui_io23 + &wui_io24 &wui_io25 &wui_io26 &wui_io27>; + }; + + gpio3: gpio@40087000 { + wui-maps = <&wui_io30 &wui_io31 &wui_io32 &wui_io33 + &wui_io34 &wui_io35 &wui_io36 &wui_io37>; + }; + + gpio4: gpio@40089000 { + wui-maps = <&wui_io40 &wui_io41 &wui_io42 &wui_io43 + &wui_io44 &wui_io45 &wui_io46 &wui_io47>; + }; + + gpio5: gpio@4008b000 { + wui-maps = <&wui_io50 &wui_io51 &wui_io52 &wui_io53 + &wui_io54 &wui_io55 &wui_io56 &wui_io57>; + }; + + gpio6: gpio@4008d000 { + wui-maps = <&wui_io60 &wui_io61 &wui_io62 &wui_io63 + &wui_io64 &wui_io65 &wui_io66 &wui_io67>; + }; + + gpio7: gpio@4008f000 { + wui-maps = <&wui_io70 &wui_io71 &wui_io72 &wui_io73 + &wui_io74 &wui_io75 &wui_io76 &wui_io77>; + }; + + gpio8: gpio@40091000 { + wui-maps = <&wui_io80 &wui_io81 &wui_io82 &wui_io83 + &wui_io84 &wui_io85 &wui_io86 &wui_io87>; + }; + + gpio9: gpio@40093000 { + wui-maps = <&wui_io90 &wui_io91 &wui_io92 &wui_io93 + &wui_io94 &wui_io95 &wui_io96 &wui_io97>; + }; + + gpioa: gpio@40095000 { + wui-maps = <&wui_ioa0 &wui_ioa1 &wui_ioa2 &wui_ioa3 + &wui_ioa4 &wui_ioa5 &wui_ioa6 &wui_ioa7>; + }; + + gpiob: gpio@40097000 { + wui-maps = <&wui_iob0 &wui_iob1 &wui_iob2 &wui_iob3 + &wui_iob4 &wui_iob5 &wui_iob6 &wui_iob7>; + }; + + gpioc: gpio@40099000 { + wui-maps = <&wui_ioc0 &wui_ioc1 &wui_ioc2 &wui_ioc3 + &wui_ioc4 &wui_ioc5 &wui_ioc6 &wui_ioc7>; + }; + + gpiod: gpio@4009b000 { + wui-maps = <&wui_iod0 &wui_iod1 &wui_iod2 &wui_iod3 + &wui_iod4 &wui_iod5 &wui_iod6 &wui_iod7>; + }; + + gpioe: gpio@4009d000 { + wui-maps = <&wui_ioe0 &wui_ioe1 &wui_ioe2 &wui_ioe3 + &wui_ioe4 &wui_ioe5 &wui_ioe6 &wui_none>; + }; + + gpiof: gpio@4009f000 { + wui-maps = <&wui_iof0 &wui_iof1 &wui_iof2 &wui_iof3 + &wui_none &wui_none &wui_none &wui_none>; + }; }; soc-if { diff --git a/dts/arm/nuvoton/npcm/npcm4/npcm4-miwus-wui-map.dtsi b/dts/arm/nuvoton/npcm/npcm4/npcm4-miwus-wui-map.dtsi new file mode 100644 index 00000000000000..481ba366e4e789 --- /dev/null +++ b/dts/arm/nuvoton/npcm/npcm4/npcm4-miwus-wui-map.dtsi @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Common Wake-Up Unit Input (WUI) mapping configurations in npcm family */ +#include + +/* Specific Wake-Up Unit Input (WUI) mapping configurations in npcm4 series */ +/ { + /* Mapping between MIWU wui bits and source device */ + npcm-miwus-wui-map { + compatible = "nuvoton,npcm-miwu-wui-map"; + }; +}; diff --git a/dts/bindings/gpio/nuvoton,npcm-gpio.yaml b/dts/bindings/gpio/nuvoton,npcm-gpio.yaml new file mode 100644 index 00000000000000..ace4f853232eb6 --- /dev/null +++ b/dts/bindings/gpio/nuvoton,npcm-gpio.yaml @@ -0,0 +1,36 @@ +# Copyright (c) 2024 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +description: Nuvoton, NPCM-GPIO node + +compatible: "nuvoton,npcm-gpio" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + + index: + type: int + required: true + description: index of gpio device + + wui-maps: + type: phandles + required: true + description: | + Mapping table between Wake-Up Input (WUI) and 8 IOs belong to this device. + Please notice not all IOs connect to WUIs. + In this case, it will be presented by wui_none. + + For example the WUI mapping on NPCM4 GPIO8 would be + wui-maps = <&wui_io80 &wui_io81 &wui_io82 &wui_io83 + &wui_none &wui_none &wui_io86 &wui_io87>; + + "#gpio-cells": + const: 2 + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/interrupt-controller/nuvoton,npcm-miwu-wui-map.yaml b/dts/bindings/interrupt-controller/nuvoton,npcm-miwu-wui-map.yaml new file mode 100644 index 00000000000000..f4d6d21c93056d --- /dev/null +++ b/dts/bindings/interrupt-controller/nuvoton,npcm-miwu-wui-map.yaml @@ -0,0 +1,13 @@ +# Copyright (c) 2024 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +description: NPCM-MIWU Wake-Up Unit Input (WUI) mapping child node + +compatible: "nuvoton,npcm-miwu-wui-map" + +child-binding: + description: Child node to present the mapping between input of MIWU and its source device + properties: + miwus: + type: phandle-array + required: true diff --git a/dts/bindings/interrupt-controller/nuvoton,npcm-miwu.yaml b/dts/bindings/interrupt-controller/nuvoton,npcm-miwu.yaml new file mode 100644 index 00000000000000..1bed91c845edaa --- /dev/null +++ b/dts/bindings/interrupt-controller/nuvoton,npcm-miwu.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2024 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +description: Nuvoton, NPCM Multi-Input Wake-Up Unit (MIWU) node + +compatible: "nuvoton,npcm-miwu" + +include: [base.yaml] + +properties: + index: + type: int + required: true + description: index of miwu device + + "#miwu-cells": + type: int + required: true + description: Number of items to present a MIWU input source specifier + +miwu-cells: + - group + - bit diff --git a/soc/nuvoton/npcm/common/soc_gpio.h b/soc/nuvoton/npcm/common/soc_gpio.h new file mode 100644 index 00000000000000..7d83ce0a2e6377 --- /dev/null +++ b/soc/nuvoton/npcm/common/soc_gpio.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2024 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _NUVOTON_NPCM_SOC_GPIO_H_ +#define _NUVOTON_NPCM_SOC_GPIO_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Pin number for each GPIO device */ +#define NPCM_GPIO_PORT_PIN_NUM 8U + +/** + * @brief Get GPIO device instance by port index + * + * @param port GPIO device index + * + * @retval Pointer to structure device + * @retval NULL Invalid parameter of GPIO port index + */ +const struct device *npcm_get_gpio_dev(int port); + +/** + * @brief Enable the connection between io pads and GPIO instance + * + * @param dev Pointer to device structure for the gpio driver instance. + * @param pin Pin number. + */ +void npcm_gpio_enable_io_pads(const struct device *dev, int pin); + +/** + * @brief Disable the connection between io pads and GPIO instance + * + * @param dev Pointer to device structure for the gpio driver instance. + * @param pin Pin number. + */ +void npcm_gpio_disable_io_pads(const struct device *dev, int pin); + +#ifdef __cplusplus +} +#endif + +#endif /* _NUVOTON_NPCM_SOC_GPIO_H_ */ diff --git a/soc/nuvoton/npcm/common/soc_miwu.h b/soc/nuvoton/npcm/common/soc_miwu.h new file mode 100644 index 00000000000000..620f957de14b88 --- /dev/null +++ b/soc/nuvoton/npcm/common/soc_miwu.h @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2024 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _NUVOTON_NPCM_SOC_MIWU_H_ +#define _NUVOTON_NPCM_SOC_MIWU_H_ + +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum miwu_table { + NPCM_MIWU_TABLE_0, + NPCM_MIWU_TABLE_1, + NPCM_MIWU_TABLE_2, + NPCM_MIWU_TABLE_COUNT +}; + +enum miwu_group { + NPCM_MIWU_GROUP_1, + NPCM_MIWU_GROUP_2, + NPCM_MIWU_GROUP_3, + NPCM_MIWU_GROUP_4, + NPCM_MIWU_GROUP_5, + NPCM_MIWU_GROUP_6, + NPCM_MIWU_GROUP_7, + NPCM_MIWU_GROUP_8, + NPCM_MIWU_GROUP_COUNT +}; + +#define NPCM_MIWU_TABLE_NONE NPCM_MIWU_TABLE_COUNT + +/* Interrupt modes supported by npcm miwu modules */ +enum miwu_int_mode { + NPCM_MIWU_MODE_LEVEL, + NPCM_MIWU_MODE_EDGE, +}; + +/* Interrupt trigger modes supported by npcm miwu modules */ +enum miwu_int_trig { + NPCM_MIWU_TRIG_LOW, /** Edge failing or active low detection */ + NPCM_MIWU_TRIG_HIGH, /** Edge rising or active high detection */ + NPCM_MIWU_TRIG_BOTH, /** Both edge rising and failing detection */ +}; + +/** + * @brief NPCM wake-up input source structure + * + * Used to indicate a Wake-Up Input source (WUI) belongs to which group and bit + * of Multi-Input Wake-Up Unit (MIWU) modules. + */ +struct npcm_wui { + uint8_t table : 2; /** A source belongs to which MIWU table. */ + uint8_t group : 3; /** A source belongs to which group of MIWU table. */ + uint8_t bit : 3; /** A source belongs to which bit of MIWU group. */ +}; + +/** + * Define npcm miwu driver callback handler signature for wake-up input source + * of generic hardware. Its parameters contain the device issued interrupt + * and corresponding WUI source. + */ +typedef void (*miwu_dev_callback_handler_t)(const struct device *source, + struct npcm_wui *wui); + +/** + * @brief MIWU/GPIO information structure + * + * It contains both GPIO and MIWU information which is stored in unused field + * of struct gpio_port_pins_t since a interested mask of pins is only 8 bits. + * Beware the size of such structure must equal struct gpio_port_pins_t. + */ +struct miwu_io_params { + uint8_t pin_mask; /** A mask of pins the callback is interested in. */ + uint8_t reserved; + uint8_t gpio_port; /** GPIO device index */ + struct npcm_wui wui; /** Wake-up input source of GPIO */ +}; + +/** + * @brief MIWU callback structure for a GPIO input + * + * Used to register a GPIO callback in the driver instance callback list. + * Beware such structure should not be allocated on stack and its size must + * equal struct gpio_callback. + * + * Note: To help setting it, see npcx_miwu_init_gpio_callback() below + */ +struct miwu_io_callback { + /** Node of single-linked list */ + sys_snode_t node; + /** Callback function being called when GPIO event occurred */ + gpio_callback_handler_t handler; + /** GPIO callback parameters used in MIWU ISR */ + struct miwu_io_params params; +}; + +/** + * @brief MIWU callback structure for a device input + * + * Used to register a generic hardware device callback in the driver instance + * callback list. Beware such structure should not be allocated on stack. + * + * Note: To help setting it, see npcm_miwu_init_dev_callback() below + */ +struct miwu_dev_callback { + /** Node of single-linked list */ + sys_snode_t node; + /** Callback function being called when device event occurred */ + miwu_dev_callback_handler_t handler; + /** Device instance register callback function */ + const struct device *source; + /* Wake-up input source */ + struct npcm_wui wui; +}; + +/** + * @brief Enable interrupt of the wake-up input source + * + * @param A pointer on wake-up input source + */ +void npcm_miwu_irq_enable(const struct npcm_wui *wui); + +/** + * @brief Disable interrupt of the wake-up input source + * + * @param wui A pointer on wake-up input source + */ +void npcm_miwu_irq_disable(const struct npcm_wui *wui); + +/** + * @brief Connect io to the wake-up input source + * + * @param wui A pointer on wake-up input source + */ +void npcm_miwu_io_enable(const struct npcm_wui *wui); + +/** + * @brief Disconnect io to the wake-up input source + * + * @param wui A pointer on wake-up input source + */ +void npcm_miwu_io_disable(const struct npcm_wui *wui); + +/** + * @brief Get interrupt state of the wake-up input source + * + * @param wui A pointer on wake-up input source + * + * @retval 0 if interrupt is disabled, otherwise interrupt is enabled + */ +bool npcm_miwu_irq_get_state(const struct npcm_wui *wui); + +/** + * @brief Get & clear interrupt pending bit of the wake-up input source + * + * @param wui A pointer on wake-up input source + * + * @retval 1 if interrupt is pending + */ +bool npcm_miwu_irq_get_and_clear_pending(const struct npcm_wui *wui); + +/** + * @brief Configure interrupt type of the wake-up input source + * + * @param wui Pointer to wake-up input source for configuring + * @param mode Interrupt mode supported by NPCM MIWU + * @param trig Interrupt trigger mode supported by NPCM MIWU + * + * @retval 0 If successful + * @retval -EINVAL Invalid parameters + */ +int npcm_miwu_interrupt_configure(const struct npcm_wui *wui, + enum miwu_int_mode mode, enum miwu_int_trig trig); + +/** + * @brief Function to initialize a struct miwu_io_callback properly + * + * @param callback Pointer to io callback structure for initialization + * @param io_wui Pointer to wake-up input IO source + * @param port GPIO port issued a callback function + */ +void npcm_miwu_init_gpio_callback(struct miwu_io_callback *callback, + const struct npcm_wui *io_wui, int port); + +/** + * @brief Function to initialize a struct miwu_dev_callback properly + * + * @param callback Pointer to device callback structure for initialization + * @param dev_wui Pointer to wake-up input device source + * @param handler A function called when its device input event issued + * @param source Pointer to device instance issued a callback function + */ +void npcm_miwu_init_dev_callback(struct miwu_dev_callback *callback, + const struct npcm_wui *dev_wui, + miwu_dev_callback_handler_t handler, + const struct device *source); + +/** + * @brief Function to insert or remove a IO callback from a callback list + * + * @param callback Pointer to io callback structure + * @param set A boolean indicating insertion or removal of the callback + * + * @retval 0 If successful. + * @retval -EINVAL Invalid parameters + */ +int npcm_miwu_manage_gpio_callback(struct miwu_io_callback *callback, bool set); + + +/** + * @brief Function to insert or remove a device callback from a callback list + * + * @param callback Pointer to device callback structure + * @param set A boolean indicating insertion or removal of the callback + * + * @retval 0 If successful. + * @retval -EINVAL Invalid parameters + */ +int npcm_miwu_manage_dev_callback(struct miwu_dev_callback *cb, bool set); + +#ifdef __cplusplus +} +#endif +#endif /* _NUVOTON_NPCM_SOC_MIWU_H_ */