pinctrl: npcx: add pinctrl support for psl pads

This CL introduces how to configure PSL (Power Switch Logic) pads
properties such as input detection mode/polarity, pin-muxing and so
on via pinctrl mechanism. It includes:

1. Add two pinctrl properties and their enums for PSL input
   detection configuration.
    psl-in-mode:
      - "level"
      - "mode"
    psl-in-pole:
      - "low-falling"
      - "high-rising"

2. Add macro functions to get PSL input detection and pin-muxing
   configurations from 'pinmux', 'psl-offset' abd 'psl-polarity'
   properties.

Here is an example to configure PSL_IN2 as the PSL detection input and
its mode and polarity.

/* A falling edge detection type for PSL_IN2 */
&psl_in2_gp00 {
	psl-in-mode = "edge";
	psl-in-pol = "low-falling";
};

A device will be introduced later which uses this pinctrl node to
configure PSL input detection settings and how to turn off VCC1 power
rail by PSL_OUT.

Signed-off-by: Mulin Chao <mlchao@nuvoton.com>
This commit is contained in:
Mulin Chao 2022-04-06 20:20:17 -07:00 committed by Fabio Baltieri
commit 851e357aa4
8 changed files with 166 additions and 9 deletions

View file

@ -9,12 +9,14 @@
/* Driver config */ /* Driver config */
struct npcx_pinctrl_config { struct npcx_pinctrl_config {
/* scfg device base address */ /* Device base address used for pinctrl driver */
uintptr_t base_scfg; uintptr_t base_scfg;
uintptr_t base_glue;
}; };
static const struct npcx_pinctrl_config npcx_pinctrl_cfg = { static const struct npcx_pinctrl_config npcx_pinctrl_cfg = {
.base_scfg = DT_REG_ADDR_BY_NAME(DT_NODELABEL(scfg), scfg), .base_scfg = NPCX_SCFG_REG_ADDR,
.base_glue = NPCX_GLUE_REG_ADDR,
}; };
/* PWM pinctrl config */ /* PWM pinctrl config */
@ -130,6 +132,27 @@ static void npcx_periph_configure(const pinctrl_soc_pin_t *pin, uintptr_t reg)
} }
} }
static void npcx_psl_input_detection_configure(const pinctrl_soc_pin_t *pin)
{
struct glue_reg *inst_glue = (struct glue_reg *)(npcx_pinctrl_cfg.base_glue);
const uintptr_t scfg_base = npcx_pinctrl_cfg.base_scfg;
const struct npcx_psl_input *psl_in = (const struct npcx_psl_input *)&pin->cfg.psl_in;
/* Configure detection polarity of PSL input pads */
if (pin->flags.psl_in_polarity == NPCX_PSL_IN_POL_HIGH) {
NPCX_DEVALT(scfg_base, psl_in->pol_group) |= BIT(psl_in->pol_bit);
} else {
NPCX_DEVALT(scfg_base, psl_in->pol_group) &= ~BIT(psl_in->pol_bit);
}
/* Configure detection mode of PSL input pads */
if (pin->flags.psl_in_mode == NPCX_PSL_IN_MODE_EDGE) {
inst_glue->PSL_CTS |= NPCX_PSL_CTS_MODE_BIT(psl_in->port);
} else {
inst_glue->PSL_CTS &= ~NPCX_PSL_CTS_MODE_BIT(psl_in->port);
}
}
/* Pinctrl API implementation */ /* Pinctrl API implementation */
int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt,
uintptr_t reg) uintptr_t reg)
@ -138,7 +161,15 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt,
/* Configure all peripheral devices' properties here. */ /* Configure all peripheral devices' properties here. */
for (uint8_t i = 0; i < pin_cnt; i++) { for (uint8_t i = 0; i < pin_cnt; i++) {
if (pins[i].flags.type == NPCX_PINCTRL_TYPE_PERIPH) {
/* Configure peripheral device's pinmux functionality */
npcx_periph_configure(&pins[i], reg); npcx_periph_configure(&pins[i], reg);
} else if (pins[i].flags.type == NPCX_PINCTRL_TYPE_PSL_IN) {
/* Configure SPL input's detection mode */
npcx_psl_input_detection_configure(&pins[i]);
} else {
return -ENOTSUP;
}
} }
return 0; return 0;

View file

@ -342,18 +342,26 @@
/* PSL peripheral interfaces. */ /* PSL peripheral interfaces. */
/omit-if-no-ref/ psl_in1_gpd2: periph-psl-in1 { /omit-if-no-ref/ psl_in1_gpd2: periph-psl-in1 {
pinmux = <&altd_npsl_in1_sl>; pinmux = <&altd_npsl_in1_sl>;
psl-offset = <0>;
psl-polarity = <&altd_psl_in1_ahi>;
}; };
/omit-if-no-ref/ psl_in2_gp00: periph-psl-in2 { /omit-if-no-ref/ psl_in2_gp00: periph-psl-in2 {
pinmux = <&altd_npsl_in2_sl>; pinmux = <&altd_npsl_in2_sl>;
psl-offset = <1>;
psl-polarity = <&altd_psl_in2_ahi>;
}; };
/omit-if-no-ref/ psl_in3_gp01: periph-psl-in3 { /omit-if-no-ref/ psl_in3_gp01: periph-psl-in3 {
pinmux = <&altd_psl_in3_sl>; pinmux = <&altd_psl_in3_sl>;
psl-offset = <2>;
psl-polarity = <&altd_psl_in3_ahi>;
}; };
/omit-if-no-ref/ psl_in4_gp02: periph-psl-in4 { /omit-if-no-ref/ psl_in4_gp02: periph-psl-in4 {
pinmux = <&altd_psl_in4_sl>; pinmux = <&altd_psl_in4_sl>;
psl-offset = <3>;
psl-polarity = <&altd_psl_in4_ahi>;
}; };
/* UART peripheral interfaces */ /* UART peripheral interfaces */

View file

@ -350,18 +350,26 @@
/* PSL peripheral interfaces */ /* PSL peripheral interfaces */
/omit-if-no-ref/ psl_in1_gpd2: periph-psl-in1 { /omit-if-no-ref/ psl_in1_gpd2: periph-psl-in1 {
pinmux = <&altd_npsl_in1_sl>; pinmux = <&altd_npsl_in1_sl>;
psl-offset = <0>;
psl-polarity = <&altd_psl_in1_ahi>;
}; };
/omit-if-no-ref/ psl_in2_gp00: periph-psl-in2 { /omit-if-no-ref/ psl_in2_gp00: periph-psl-in2 {
pinmux = <&altd_npsl_in2_sl>; pinmux = <&altd_npsl_in2_sl>;
psl-offset = <1>;
psl-polarity = <&altd_psl_in2_ahi>;
}; };
/omit-if-no-ref/ psl_in3_gp01: periph-psl-in3 { /omit-if-no-ref/ psl_in3_gp01: periph-psl-in3 {
pinmux = <&altd_psl_in3_sl>; pinmux = <&altd_psl_in3_sl>;
psl-offset = <2>;
psl-polarity = <&altd_psl_in3_ahi>;
}; };
/omit-if-no-ref/ psl_in4_gp02: periph-psl-in4 { /omit-if-no-ref/ psl_in4_gp02: periph-psl-in4 {
pinmux = <&altd_psl_in4_sl>; pinmux = <&altd_psl_in4_sl>;
psl-offset = <3>;
psl-polarity = <&altd_psl_in4_ahi>;
}; };
/omit-if-no-ref/ psl_gpo_gpd7: periph-psl-gpo { /omit-if-no-ref/ psl_gpo_gpd7: periph-psl-gpo {

View file

@ -14,6 +14,8 @@ description: |
Custom pin properties for npcx series are available also: Custom pin properties for npcx series are available also:
- pinmux-locked: Lock pinmux configuration for peripheral device - pinmux-locked: Lock pinmux configuration for peripheral device
- pinmux-gpio: Inverse pinmux back to gpio - pinmux-gpio: Inverse pinmux back to gpio
- psl-in-mode: Select the assertion detection mode of PSL input
- psl-in-pol: Select the assertion detection polarity of PSL input
An example for NPCX7 family, include the chip level pinctrl DTSI file in the An example for NPCX7 family, include the chip level pinctrl DTSI file in the
board level DTS: board level DTS:
@ -61,6 +63,17 @@ child-binding:
description: | description: |
A map to PUPD_ENn register/bit that enable pull-up/down of NPCX peripheral devices. A map to PUPD_ENn register/bit that enable pull-up/down of NPCX peripheral devices.
Please don't overwrite this property in the board-level DT driver. Please don't overwrite this property in the board-level DT driver.
psl-offset:
type: int
description: |
Offset to PSL_CTS register that is used for PSL input's status and detection mode.
Please don't overwrite this property in the board-level DT driver.
psl-polarity:
type: phandle
required: false
description: |
A map to DEVALTn that configures detection polarity of PSL input pads.
Please don't overwrite this property in the board-level DT driver.
pinmux-locked: pinmux-locked:
required: false required: false
type: boolean type: boolean
@ -69,3 +82,23 @@ child-binding:
required: false required: false
type: boolean type: boolean
description: Inverse pinmux selection to GPIO description: Inverse pinmux selection to GPIO
psl-in-mode:
type: string
required: false
description: |
The assertion detection mode of PSL input selection
- "level": Select the detection mode to level detection
- "edge": Select the detection mode to edge detection
enum:
- "level"
- "edge"
psl-in-pol:
type: string
required: false
description: |
The assertion detection polarity of PSL input selection
- "low-falling": Select the detection polarity to low/falling
- "high-rising": Select the detection polarity to high/rising
enum:
- "low-falling"
- "high-rising"

View file

@ -16,6 +16,7 @@
*/ */
enum npcx_pinctrl_type { enum npcx_pinctrl_type {
NPCX_PINCTRL_TYPE_PERIPH, NPCX_PINCTRL_TYPE_PERIPH,
NPCX_PINCTRL_TYPE_PSL_IN,
NPCX_PINCTRL_TYPE_RESERVED, NPCX_PINCTRL_TYPE_RESERVED,
}; };
@ -45,6 +46,22 @@ enum npcx_io_drive_type {
NPCX_DRIVE_TYPE_OPEN_DRAIN, NPCX_DRIVE_TYPE_OPEN_DRAIN,
}; };
/**
* @brief Suppoerted PSL input detection mode in NPCX series
*/
enum npcx_psl_in_mode {
NPCX_PSL_IN_MODE_LEVEL,
NPCX_PSL_IN_MODE_EDGE,
};
/**
* @brief Suppoerted PSL input detection polarity in NPCX series
*/
enum npcx_psl_in_pol {
NPCX_PSL_IN_POL_LOW,
NPCX_PSL_IN_POL_HIGH,
};
/** /**
* @brief NPCX peripheral device configuration structure * @brief NPCX peripheral device configuration structure
* *
@ -64,6 +81,21 @@ struct npcx_periph {
uint16_t reserved: 2; uint16_t reserved: 2;
} __packed; } __packed;
/**
* @brief NPCX Power Switch Logic (PSL) input pad configuration structure
*
* Used to indicate a Power Switch Logic (PSL) input detection configuration
* such as detection polarity, port number, and so on.
*/
struct npcx_psl_input {
/** Indicate a PSL input port number. */
uint16_t port: 5;
/** Related register group for detection polarity of PSL input. */
uint16_t pol_group: 8;
/** Related register bit for detection polarity of PSL input. */
uint16_t pol_bit: 3;
} __packed;
/** /**
* @brief Type for NPCX pin configuration. Please make sure the size of this * @brief Type for NPCX pin configuration. Please make sure the size of this
* structure is 4 bytes in case the impact of ROM usage. * structure is 4 bytes in case the impact of ROM usage.
@ -71,6 +103,7 @@ struct npcx_periph {
struct npcx_pinctrl { struct npcx_pinctrl {
union { union {
struct npcx_periph periph; struct npcx_periph periph;
struct npcx_psl_input psl_in;
uint16_t cfg_word; uint16_t cfg_word;
} cfg; } cfg;
struct { struct {
@ -82,7 +115,10 @@ struct npcx_pinctrl {
/** Properties used for io-pad. */ /** Properties used for io-pad. */
enum npcx_io_bias_type io_bias_type :2; enum npcx_io_bias_type io_bias_type :2;
enum npcx_io_drive_type io_drive_type :1; enum npcx_io_drive_type io_drive_type :1;
uint16_t reserved :1; /** Properties used for PSL input. */
enum npcx_psl_in_mode psl_in_mode :1;
enum npcx_psl_in_pol psl_in_polarity :1;
uint16_t reserved :7;
} flags; } flags;
} __packed; } __packed;
@ -106,6 +142,10 @@ typedef struct npcx_pinctrl pinctrl_soc_pin_t;
UTIL_AND(DT_PROP(node_id, drive_open_drain), \ UTIL_AND(DT_PROP(node_id, drive_open_drain), \
DT_NODE_HAS_PROP(node_periph, pwm_channel)) DT_NODE_HAS_PROP(node_periph, pwm_channel))
#define Z_PINCTRL_NPCX_HAS_PSL_IN_PROP(node_id) \
UTIL_AND(DT_NODE_HAS_PROP(node_id, psl_in_pol), \
DT_NODE_HAS_PROP(node_id, psl_in_mode))
/** /**
* @brief Utility macro to initialize a periphral pinmux configuration. * @brief Utility macro to initialize a periphral pinmux configuration.
* *
@ -152,6 +192,23 @@ typedef struct npcx_pinctrl pinctrl_soc_pin_t;
.cfg.periph.group = DT_PROP(node_periph, pwm_channel), \ .cfg.periph.group = DT_PROP(node_periph, pwm_channel), \
}, },
/*
* @brief Utility macro to initialize a Power Switch Logic (PSL) input detection
* configurations.
*
* @param node_id Node identifier.
* @param prop Property name for pull-up/down configuration. (i.e. 'polarity')
*/
#define Z_PINCTRL_NPCX_PSL_IN_DETECT_CONF_INIT(node_id, prop) \
{ \
.flags.type = NPCX_PINCTRL_TYPE_PSL_IN, \
.flags.psl_in_mode = DT_ENUM_IDX(node_id, psl_in_mode), \
.flags.psl_in_polarity = DT_ENUM_IDX(node_id, psl_in_pol), \
.cfg.psl_in.port = DT_PROP(node_id, psl_offset), \
.cfg.psl_in.pol_group = DT_PHA(DT_PROP(node_id, prop), alts, group), \
.cfg.psl_in.pol_bit = DT_PHA(DT_PROP(node_id, prop), alts, bit), \
},
/** /**
* @brief Utility macro to initialize all peripheral confiurations for each pin. * @brief Utility macro to initialize all peripheral confiurations for each pin.
* *
@ -167,6 +224,9 @@ typedef struct npcx_pinctrl pinctrl_soc_pin_t;
COND_CODE_1(Z_PINCTRL_NPCX_HAS_PUPD_PROP(DT_PROP_BY_IDX(node_id, prop, idx)), \ COND_CODE_1(Z_PINCTRL_NPCX_HAS_PUPD_PROP(DT_PROP_BY_IDX(node_id, prop, idx)), \
(Z_PINCTRL_NPCX_PERIPH_PUPD_INIT( \ (Z_PINCTRL_NPCX_PERIPH_PUPD_INIT( \
DT_PROP_BY_IDX(node_id, prop, idx), periph_pupd)), ()) \ DT_PROP_BY_IDX(node_id, prop, idx), periph_pupd)), ()) \
COND_CODE_1(Z_PINCTRL_NPCX_HAS_PSL_IN_PROP(DT_PROP_BY_IDX(node_id, prop, idx)), \
(Z_PINCTRL_NPCX_PSL_IN_DETECT_CONF_INIT( \
DT_PROP_BY_IDX(node_id, prop, idx), psl_polarity)), ()) \
COND_CODE_1(DT_NODE_HAS_PROP(DT_PROP_BY_IDX(node_id, prop, idx), pinmux), \ COND_CODE_1(DT_NODE_HAS_PROP(DT_PROP_BY_IDX(node_id, prop, idx), pinmux), \
(Z_PINCTRL_NPCX_PERIPH_PINMUX_INIT( \ (Z_PINCTRL_NPCX_PERIPH_PINMUX_INIT( \
DT_PROP_BY_IDX(node_id, prop, idx), pinmux)), ()) DT_PROP_BY_IDX(node_id, prop, idx), pinmux)), ())

View file

@ -280,6 +280,12 @@ struct glue_reg {
volatile uint8_t PSL_CTS; volatile uint8_t PSL_CTS;
}; };
/* GLUE register fields */
/* PSL input detection mode is configured by bits 7:4 of PSL_CTS */
#define NPCX_PSL_CTS_MODE_BIT(bit) BIT(bit + 4)
/* PSL input assertion events are reported by bits 3:0 of PSL_CTS */
#define NPCX_PSL_CTS_EVENT_BIT(bit) BIT(bit)
/* /*
* Universal Asynchronous Receiver-Transmitter (UART) device registers * Universal Asynchronous Receiver-Transmitter (UART) device registers
*/ */

View file

@ -52,11 +52,6 @@ static const struct npcx_scfg_config npcx_scfg_cfg = {
#define HAL_GLUE_INST() (struct glue_reg *)(npcx_scfg_cfg.base_glue) #define HAL_GLUE_INST() (struct glue_reg *)(npcx_scfg_cfg.base_glue)
/* PSL input detection mode is configured by bits 7:4 of PSL_CTS */
#define NPCX_PSL_CTS_MODE_BIT(bit) BIT(bit + 4)
/* PSL input assertion events are reported by bits 3:0 of PSL_CTS */
#define NPCX_PSL_CTS_EVENT_BIT(bit) BIT(bit)
/* Pin-control local functions */ /* Pin-control local functions */
static void npcx_pinctrl_alt_sel(const struct npcx_alt *alt, int alt_func) static void npcx_pinctrl_alt_sel(const struct npcx_alt *alt, int alt_func)
{ {

View file

@ -700,4 +700,20 @@
#define NPCX_BOOTER_IS_HIF_TYPE_SET() \ #define NPCX_BOOTER_IS_HIF_TYPE_SET() \
DT_PROP(DT_PATH(booter_variant), hif_type_auto) DT_PROP(DT_PATH(booter_variant), hif_type_auto)
/**
* @brief Helper macro to get address of system configuration module which is
* used by serval peripheral device drivers in npcx series.
*
* @return base address of system configuration module.
*/
#define NPCX_SCFG_REG_ADDR DT_REG_ADDR_BY_NAME(DT_NODELABEL(scfg), scfg)
/**
* @brief Helper macro to get address of system glue module which is
* used by serval peripheral device drivers in npcx series.
*
* @return base address of system glue module.
*/
#define NPCX_GLUE_REG_ADDR DT_REG_ADDR_BY_NAME(DT_NODELABEL(scfg), glue)
#endif /* _NUVOTON_NPCX_SOC_DT_H_ */ #endif /* _NUVOTON_NPCX_SOC_DT_H_ */