drivers: pinctrl: npcx: add initial pin-controller driver

This CL is the initial version for npcx pinctrl driver and introduces
pinctrl nodes for both IO-pads and peripheral devices for each npcx
series. Users can set pin configuration via these nodes in the board
layout DT file. It also wraps all configurations related to pin-muxing
in pinctrl_soc.h. Regarding the other pin properties, we will implement
them later.

Signed-off-by: Mulin Chao <mlchao@nuvoton.com>
This commit is contained in:
Mulin Chao 2022-02-21 01:19:31 -08:00 committed by Maureen Helm
commit d53d574bf0
14 changed files with 1225 additions and 0 deletions

View file

@ -7,6 +7,7 @@ zephyr_library_sources_ifdef(CONFIG_PINCTRL_TELINK_B91 pinctrl_b91.c)
zephyr_library_sources_ifdef(CONFIG_PINCTRL_GD32_AF pinctrl_gd32_af.c)
zephyr_library_sources_ifdef(CONFIG_PINCTRL_GD32_AFIO pinctrl_gd32_afio.c)
zephyr_library_sources_ifdef(CONFIG_PINCTRL_ITE_IT8XXX2 pinctrl_ite_it8xxx2.c)
zephyr_library_sources_ifdef(CONFIG_PINCTRL_NPCX pinctrl_npcx.c)
zephyr_library_sources_ifdef(CONFIG_PINCTRL_NRF pinctrl_nrf.c)
zephyr_library_sources_ifdef(CONFIG_PINCTRL_RCAR_PFC pfc_rcar.c)
zephyr_library_sources_ifdef(CONFIG_PINCTRL_RPI_PICO pinctrl_rpi_pico.c)

View file

@ -32,6 +32,7 @@ config PINCTRL_DYNAMIC
source "drivers/pinctrl/Kconfig.b91"
source "drivers/pinctrl/Kconfig.gd32"
source "drivers/pinctrl/Kconfig.it8xxx2"
source "drivers/pinctrl/Kconfig.npcx"
source "drivers/pinctrl/Kconfig.nrf"
source "drivers/pinctrl/Kconfig.rcar"
source "drivers/pinctrl/Kconfig.rpi_pico"

View file

@ -0,0 +1,15 @@
# NPCX Pin Controller configuration options
# Copyright (c) 2022 Nuvoton Technology Corporation.
# SPDX-License-Identifier: Apache-2.0
DT_COMPAT_ST_PINCTRL_NPCX := nuvoton,npcx-pinctrl
config PINCTRL_NPCX
bool "Nuvoton NPCX embedded controller (EC) pin controller driver"
depends on SOC_FAMILY_NPCX
select PINCTRL_STORE_REG
default $(dt_compat_enabled,$(DT_COMPAT_ST_PINCTRL_NPCX))
help
This option enables the pin controller driver for NPCX family of
processors.

View file

@ -0,0 +1,114 @@
/*
* Copyright (c) 2022 Nuvoton Technology Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <assert.h>
#include <zephyr/drivers/pinctrl.h>
#include <soc.h>
/* Driver config */
struct npcx_pinctrl_config {
/* scfg device base address */
uintptr_t base_scfg;
};
static const struct npcx_pinctrl_config npcx_pinctrl_cfg = {
.base_scfg = DT_REG_ADDR_BY_NAME(DT_NODELABEL(scfg), scfg),
};
/* Pin-control local functions for peripheral devices */
static bool npcx_periph_pinmux_has_lock(int group)
{
#if defined(CONFIG_SOC_SERIES_NPCX7)
if (group == 0x00 || (group >= 0x02 && group <= 0x04) || group == 0x06 ||
group == 0x0b || group == 0x0f) {
return true;
}
#elif defined(CONFIG_SOC_SERIES_NPCX9)
if (group == 0x00 || (group >= 0x02 && group <= 0x06) || group == 0x0b ||
group == 0x0d || (group >= 0x0f && group <= 0x12)) {
return true;
}
#endif
return false;
}
static void npcx_periph_pinmux_configure(const struct npcx_periph *alt, bool is_alternate,
bool is_locked)
{
const uintptr_t scfg_base = npcx_pinctrl_cfg.base_scfg;
uint8_t alt_mask = BIT(alt->bit);
/*
* is_alternate == 0 means select GPIO, otherwise Alternate Func.
* inverted == 0:
* Set devalt bit to select Alternate Func.
* inverted == 1:
* Clear devalt bit to select Alternate Func.
*/
if (is_alternate != alt->inverted) {
NPCX_DEVALT(scfg_base, alt->group) |= alt_mask;
} else {
NPCX_DEVALT(scfg_base, alt->group) &= ~alt_mask;
}
if (is_locked && npcx_periph_pinmux_has_lock(alt->group)) {
NPCX_DEVALT_LK(scfg_base, alt->group) |= alt_mask;
}
}
static void npcx_periph_pupd_configure(const struct npcx_periph *pupd,
enum npcx_io_bias_type type)
{
const uintptr_t scfg_base = npcx_pinctrl_cfg.base_scfg;
if (type == NPCX_BIAS_TYPE_NONE) {
NPCX_PUPD_EN(scfg_base, pupd->group) &= ~BIT(pupd->bit);
} else {
NPCX_PUPD_EN(scfg_base, pupd->group) |= BIT(pupd->bit);
}
}
static void npcx_periph_pwm_drive_mode_configure(uintptr_t reg, bool is_od)
{
struct pwm_reg *const inst = (struct pwm_reg *)(reg);
if (is_od) {
inst->PWMCTLEX |= BIT(NPCX_PWMCTLEX_OD_OUT);
} else {
inst->PWMCTLEX &= ~BIT(NPCX_PWMCTLEX_OD_OUT);
}
}
static void npcx_periph_configure(const pinctrl_soc_pin_t *pin, uintptr_t reg)
{
if (pin->cfg.periph.type == NPCX_PINCTRL_TYPE_PERIPH_PINMUX) {
/* Configure peripheral device's pinmux functionality */
npcx_periph_pinmux_configure(&pin->cfg.periph,
!pin->flags.pinmux_gpio,
pin->flags.pinmux_lock);
} else if (pin->cfg.periph.type == NPCX_PINCTRL_TYPE_PERIPH_PUPD) {
/* Configure peripheral device's internal PU/PD */
npcx_periph_pupd_configure(&pin->cfg.periph,
pin->flags.io_bias_type);
} else if (pin->cfg.periph.type == NPCX_PINCTRL_TYPE_PERIPH_DRIVE) {
/* Configure peripheral device's drive mode. (Only PWM pads support it) */
npcx_periph_pwm_drive_mode_configure(reg,
pin->flags.io_drive_type == NPCX_DRIVE_TYPE_OPEN_DRAIN);
}
}
/* Pinctrl API implementation */
int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt,
uintptr_t reg)
{
ARG_UNUSED(reg);
/* Configure all peripheral devices' properties here. */
for (uint8_t i = 0; i < pin_cnt; i++) {
npcx_periph_configure(&pins[i], reg);
}
return 0;
}