drivers: pinctrl: mec5: Microchip MEC5 HAL based pinctrl driver
Add a pinctrl driver for Microchip MEC5 HAL based chips. The driver removes the YAML enum "no change" property value from the driver strength and slew rate properties. Update the shared header file in mec soc common folder to use a different Z_PINCTRL_STATE_PINCFG_INIT for MEC5. Modifications to legacy MEC172x XEC PINCTRL will be in a future PR. Signed-off-by: Scott Worley <scott.worley@microchip.com>
This commit is contained in:
parent
d12de2d6b4
commit
4fa5fc3b4c
7 changed files with 337 additions and 18 deletions
|
@ -39,5 +39,6 @@ zephyr_library_sources_ifdef(CONFIG_PINCTRL_ENE_KB1200 pinctrl_ene_kb1200.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_PINCTRL_IMX_SCU pinctrl_imx_scu.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_PINCTRL_MAX32 pinctrl_max32.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_PINCTRL_IMX_SCMI pinctrl_imx_scmi.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_PINCTRL_MCHP_MEC5 pinctrl_mchp_mec5.c)
|
||||
|
||||
add_subdirectory(renesas)
|
||||
|
|
|
@ -66,6 +66,7 @@ source "drivers/pinctrl/Kconfig.mci_io_mux"
|
|||
source "drivers/pinctrl/Kconfig.ene"
|
||||
source "drivers/pinctrl/Kconfig.zynqmp"
|
||||
source "drivers/pinctrl/Kconfig.max32"
|
||||
source "drivers/pinctrl/Kconfig.mec5"
|
||||
|
||||
rsource "renesas/Kconfig"
|
||||
|
||||
|
|
9
drivers/pinctrl/Kconfig.mec5
Normal file
9
drivers/pinctrl/Kconfig.mec5
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Copyright (c) 2024 Microchip Technology Inc.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config PINCTRL_MCHP_MEC5
|
||||
bool "Pin controller driver for MCHP MEC5 MCUs"
|
||||
default y
|
||||
depends on DT_HAS_MICROCHIP_MEC5_PINCTRL_ENABLED
|
||||
help
|
||||
Enable pin controller driver for Microchip MEC5 MCUs
|
166
drivers/pinctrl/pinctrl_mchp_mec5.c
Normal file
166
drivers/pinctrl/pinctrl_mchp_mec5.c
Normal file
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Open-RnD Sp. z o.o.
|
||||
* Copyright (c) 2021 Linaro Limited
|
||||
* Copyright (c) 2021 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2024 Microchip Technology Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT microchip_mec5_pinctrl
|
||||
|
||||
#include <zephyr/drivers/pinctrl.h>
|
||||
#include <zephyr/dt-bindings/pinctrl/mchp-xec-pinctrl.h>
|
||||
#include <mec_gpio_api.h>
|
||||
|
||||
static const struct mec_gpio_props cfg1[] = {
|
||||
{MEC_GPIO_OSEL_PROP_ID, MEC_GPIO_PROP_OSEL_CTRL},
|
||||
{MEC_GPIO_INPAD_DIS_PROP_ID, MEC_GPIO_PROP_INPAD_EN},
|
||||
};
|
||||
|
||||
/* DT enable booleans take precedence over disable booleans.
|
||||
* We initially clear alternate output disable allowing us to set output state
|
||||
* in the control register. Hardware sets output state bit in both control and
|
||||
* parallel output register bits. Alternate output disable only controls which
|
||||
* register bit is writable by the EC. We also clear the input pad disable
|
||||
* bit because we need the input pin state and we don't know if the requested
|
||||
* alternate function is input or bi-directional.
|
||||
* Note 1: hardware allows input and output to be simultaneously enabled.
|
||||
* Note 2: hardware interrupt detection is only on the input path.
|
||||
*/
|
||||
static int mec5_config_pin(uint32_t pinmux, uint32_t altf)
|
||||
{
|
||||
uint32_t conf = pinmux;
|
||||
uint32_t pin = 0, temp = 0;
|
||||
int ret = 0;
|
||||
size_t idx = 0;
|
||||
struct mec_gpio_props cfg2[12];
|
||||
|
||||
ret = mec_hal_gpio_pin_num(MCHP_XEC_PINMUX_PORT(pinmux), MCHP_XEC_PINMUX_PIN(pinmux), &pin);
|
||||
if (ret) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = mec_hal_gpio_set_props(pin, cfg1, ARRAY_SIZE(cfg1));
|
||||
if (ret) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* slew rate */
|
||||
temp = (conf >> MCHP_XEC_SLEW_RATE_POS) & MCHP_XEC_SLEW_RATE_MSK0;
|
||||
if (temp != MCHP_XEC_SLEW_RATE_MSK0) {
|
||||
cfg2[idx].prop = MEC_GPIO_SLEW_RATE_ID;
|
||||
cfg2[idx].val = (uint8_t)MEC_GPIO_SLEW_RATE_SLOW;
|
||||
if (temp == MCHP_XEC_SLEW_RATE_FAST0) {
|
||||
cfg2[idx].val = (uint8_t)MEC_GPIO_SLEW_RATE_FAST;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
/* drive strength */
|
||||
temp = (conf >> MCHP_XEC_DRV_STR_POS) & MCHP_XEC_DRV_STR_MSK0;
|
||||
if (temp != MCHP_XEC_DRV_STR_MSK0) {
|
||||
cfg2[idx].prop = MEC_GPIO_DRV_STR_ID;
|
||||
cfg2[idx].val = (uint8_t)(temp - 1u);
|
||||
idx++;
|
||||
}
|
||||
|
||||
/* Touch internal pull-up/pull-down? */
|
||||
cfg2[idx].prop = MEC_GPIO_PUD_PROP_ID;
|
||||
if (conf & BIT(MCHP_XEC_NO_PUD_POS)) {
|
||||
cfg2[idx++].val = MEC_GPIO_PROP_NO_PUD;
|
||||
} else if (conf & BIT(MCHP_XEC_PU_POS)) {
|
||||
cfg2[idx++].val = MEC_GPIO_PROP_PULL_UP;
|
||||
} else if (conf & BIT(MCHP_XEC_PD_POS)) {
|
||||
cfg2[idx++].val = MEC_GPIO_PROP_PULL_DN;
|
||||
}
|
||||
|
||||
/* Touch output enable. We always enable input */
|
||||
if (conf & (BIT(MCHP_XEC_OUT_DIS_POS) | BIT(MCHP_XEC_OUT_EN_POS))) {
|
||||
cfg2[idx].prop = MEC_GPIO_DIR_PROP_ID;
|
||||
cfg2[idx].val = MEC_GPIO_PROP_DIR_IN;
|
||||
if (conf & BIT(MCHP_XEC_OUT_EN_POS)) {
|
||||
cfg2[idx].val = MEC_GPIO_PROP_DIR_OUT;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
/* Touch output state? Bit can be set even if the direction is input only */
|
||||
if (conf & (BIT(MCHP_XEC_OUT_LO_POS) | BIT(MCHP_XEC_OUT_HI_POS))) {
|
||||
cfg2[idx].prop = MEC_GPIO_CTRL_OUT_VAL_ID;
|
||||
cfg2[idx].val = 0u;
|
||||
if (conf & BIT(MCHP_XEC_OUT_HI_POS)) {
|
||||
cfg2[idx].val = 1u;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
/* Touch output buffer type? */
|
||||
if (conf & (BIT(MCHP_XEC_PUSH_PULL_POS) | BIT(MCHP_XEC_OPEN_DRAIN_POS))) {
|
||||
cfg2[idx].prop = MEC_GPIO_OBUFT_PROP_ID;
|
||||
cfg2[idx].val = MEC_GPIO_PROP_PUSH_PULL;
|
||||
if (conf & BIT(MCHP_XEC_OPEN_DRAIN_POS)) {
|
||||
cfg2[idx].val = MEC_GPIO_PROP_OPEN_DRAIN;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
/* Always touch power gate */
|
||||
cfg2[idx].prop = MEC_GPIO_PWRGT_PROP_ID;
|
||||
cfg2[idx].val = MEC_GPIO_PROP_PWRGT_VTR;
|
||||
if (conf & BIT(MCHP_XEC_PIN_LOW_POWER_POS)) {
|
||||
cfg2[idx].val = MEC_GPIO_PROP_PWRGT_OFF;
|
||||
}
|
||||
idx++;
|
||||
|
||||
/* Always touch MUX (alternate function) */
|
||||
cfg2[idx].prop = MEC_GPIO_MUX_PROP_ID;
|
||||
cfg2[idx].val = (uint8_t)altf;
|
||||
idx++;
|
||||
|
||||
/* Always touch invert of alternate function. Need another bit to avoid touching */
|
||||
cfg2[idx].prop = MEC_GPIO_FUNC_POL_PROP_ID;
|
||||
cfg2[idx].val = MEC_GPIO_PROP_FUNC_OUT_NON_INV;
|
||||
if (conf & BIT(MCHP_XEC_FUNC_INV_POS)) {
|
||||
cfg2[idx].val = MEC_GPIO_PROP_FUNC_OUT_INV;
|
||||
}
|
||||
idx++;
|
||||
|
||||
/* HW sets output state set in control & parallel regs */
|
||||
ret = mec_hal_gpio_set_props(pin, cfg2, idx);
|
||||
if (ret) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* make output state in control read-only in control and read-write in parallel reg */
|
||||
ret = mec_hal_gpio_set_property(pin, MEC_GPIO_OSEL_PROP_ID, MEC_GPIO_PROP_OSEL_PAROUT);
|
||||
if (ret) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg)
|
||||
{
|
||||
uint32_t pinmux, func;
|
||||
int ret;
|
||||
|
||||
ARG_UNUSED(reg);
|
||||
|
||||
for (uint8_t i = 0U; i < pin_cnt; i++) {
|
||||
pinmux = pins[i];
|
||||
|
||||
func = MCHP_XEC_PINMUX_FUNC(pinmux);
|
||||
if (func >= MCHP_AFMAX) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = mec5_config_pin(pinmux, func);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -136,6 +136,7 @@
|
|||
};
|
||||
};
|
||||
pinctrl: pin-controller@40081000 {
|
||||
compatible = "microchip,mec5-pinctrl";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
reg = <0x40081000 0x1000>;
|
||||
|
|
124
dts/bindings/pinctrl/microchip,mec5-pinctrl.yaml
Normal file
124
dts/bindings/pinctrl/microchip,mec5-pinctrl.yaml
Normal file
|
@ -0,0 +1,124 @@
|
|||
# Copyright (c) 2024 Microchip Technology Inc.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: |
|
||||
Microchip XEC Pin controller Node
|
||||
Based on pincfg-node.yaml binding.
|
||||
The MCHP XEC pin controller is a singleton node responsible for controlling
|
||||
pin function selection and pin properties. For example, you can use this
|
||||
node to select peripheral pin functions.
|
||||
|
||||
The node has the 'pinctrl' node label set in your SoC's devicetree,
|
||||
so you can modify it like this:
|
||||
|
||||
&pinctrl {
|
||||
/* your modifications go here */
|
||||
};
|
||||
|
||||
All device pin configurations should be placed in child nodes of the
|
||||
'pinctrl' node, as in the spi0 example shown at the end:
|
||||
|
||||
A group can also specify shared pin properties common to all the specified
|
||||
pins, such as the 'bias-pull-up' property in group 2. Here is a list of
|
||||
supported standard pin properties:
|
||||
|
||||
- bias-disable: Disable pull-up/down (default behavior, not required).
|
||||
- bias-pull-down: Enable pull-down resistor.
|
||||
- bias-pull-up: Enable pull-up resistor.
|
||||
- drive-push-pull: Output driver is push-pull (default, not required).
|
||||
- drive-open-drain: Output driver is open-drain.
|
||||
- output-high: Set output state high when pin configured.
|
||||
- output-low: Set output state low when pin configured.
|
||||
|
||||
Custom pin properties for drive strength and slew rate are available:
|
||||
- drive-strength
|
||||
- slew-rate
|
||||
|
||||
Driver strength and slew rate hardware defaults vary by SoC and pin.
|
||||
|
||||
An example for MEC174x family, include the chip level pinctrl
|
||||
DTSI file in the board level DTS:
|
||||
|
||||
#include <microchip/mec5/mec1743qlj-a0-pinctrl.dtsi>
|
||||
|
||||
We want to use the shared SPI port of the MEC172x QMSPI controller
|
||||
and want the chip select 0 to be open-drain.
|
||||
|
||||
To change a pin's pinctrl default properties add a reference to the
|
||||
pin in the board's DTS file and set the properties.
|
||||
|
||||
&spi0 {
|
||||
pinctrl-0 = < &shd_cs0_n_gpio055
|
||||
&shd_clk_gpio056
|
||||
&shd_io0_gpio223
|
||||
&shd_io1_gpio224
|
||||
&shd_io3_gpio016 >;
|
||||
pinctrl-names = "default";
|
||||
}
|
||||
|
||||
&shd_cs0_n_gpio055 {
|
||||
drive-open-drain;
|
||||
};
|
||||
|
||||
compatible: "microchip,mec5-pinctrl"
|
||||
|
||||
include: base.yaml
|
||||
|
||||
properties:
|
||||
reg:
|
||||
required: true
|
||||
|
||||
child-binding:
|
||||
description: |
|
||||
This binding gives a base representation of the Microchip XEC pins
|
||||
configuration
|
||||
|
||||
include:
|
||||
- name: pincfg-node.yaml
|
||||
property-allowlist:
|
||||
- bias-disable
|
||||
- bias-pull-down
|
||||
- bias-pull-up
|
||||
- drive-push-pull
|
||||
- drive-open-drain
|
||||
- low-power-enable
|
||||
- output-disable
|
||||
- output-enable
|
||||
- output-high
|
||||
- output-low
|
||||
|
||||
properties:
|
||||
pinmux:
|
||||
type: int
|
||||
required: true
|
||||
description: Pinmux selection
|
||||
|
||||
slew-rate:
|
||||
type: string
|
||||
enum:
|
||||
- "low-speed"
|
||||
- "high-speed"
|
||||
description: |
|
||||
Pin speed. The default value of slew-rate is the SoC power-on-reset
|
||||
value. Please refer to the data sheet as a small number of pins
|
||||
may have a different default and some pins do not implement
|
||||
slew rate adjustment.
|
||||
|
||||
drive-strength:
|
||||
type: string
|
||||
enum:
|
||||
- "1x"
|
||||
- "2x"
|
||||
- "4x"
|
||||
- "6x"
|
||||
description: |
|
||||
Pin output drive strength for PIO and PIO-24 pin types. Default
|
||||
is "1x" for most pins. PIO pins are 2, 4, 8, or 12 mA. PIO-24 pins
|
||||
are 4, 8, 16, or 24 mA. Please refer to the data sheet for each
|
||||
pin's PIO type and default drive strength.
|
||||
|
||||
microchip,output-func-invert:
|
||||
type: boolean
|
||||
description:
|
||||
Invert polarity of an output alternate function. Input functions
|
||||
are not affected.
|
|
@ -31,28 +31,45 @@ typedef uint32_t pinctrl_soc_pin_t;
|
|||
/* initialize pinmux member fields of pinctrl_pin_t */
|
||||
#define Z_PINCTRL_MCHP_XEC_PINMUX_INIT(node_id) (uint32_t)(DT_PROP(node_id, pinmux))
|
||||
|
||||
#define Z_PINCTRL_STATE_PINCFG_INIT(node_id) \
|
||||
((DT_PROP(node_id, bias_disable) << MCHP_XEC_NO_PUD_POS) \
|
||||
| (DT_PROP(node_id, bias_pull_down) << MCHP_XEC_PD_POS) \
|
||||
| (DT_PROP(node_id, bias_pull_up) << MCHP_XEC_PU_POS) \
|
||||
| (DT_PROP(node_id, drive_push_pull) << MCHP_XEC_PUSH_PULL_POS) \
|
||||
| (DT_PROP(node_id, drive_open_drain) << MCHP_XEC_OPEN_DRAIN_POS) \
|
||||
| (DT_PROP(node_id, output_disable) << MCHP_XEC_OUT_DIS_POS) \
|
||||
| (DT_PROP(node_id, output_enable) << MCHP_XEC_OUT_EN_POS) \
|
||||
| (DT_PROP(node_id, output_high) << MCHP_XEC_OUT_HI_POS) \
|
||||
| (DT_PROP(node_id, output_low) << MCHP_XEC_OUT_LO_POS) \
|
||||
| (DT_PROP(node_id, low_power_enable) << MCHP_XEC_PIN_LOW_POWER_POS) \
|
||||
| (DT_PROP(node_id, microchip_output_func_invert) << MCHP_XEC_FUNC_INV_POS) \
|
||||
| (DT_ENUM_IDX(node_id, slew_rate) << MCHP_XEC_SLEW_RATE_POS) \
|
||||
| (DT_ENUM_IDX(node_id, drive_strength) << MCHP_XEC_DRV_STR_POS))
|
||||
#ifdef CONFIG_HAS_MEC5_HAL
|
||||
#define Z_PINCTRL_STATE_PINCFG_INIT(node_id) \
|
||||
((DT_PROP(node_id, bias_disable) << MCHP_XEC_NO_PUD_POS) | \
|
||||
(DT_PROP(node_id, bias_pull_down) << MCHP_XEC_PD_POS) | \
|
||||
(DT_PROP(node_id, bias_pull_up) << MCHP_XEC_PU_POS) | \
|
||||
(DT_PROP(node_id, drive_push_pull) << MCHP_XEC_PUSH_PULL_POS) | \
|
||||
(DT_PROP(node_id, drive_open_drain) << MCHP_XEC_OPEN_DRAIN_POS) | \
|
||||
(DT_PROP(node_id, output_disable) << MCHP_XEC_OUT_DIS_POS) | \
|
||||
(DT_PROP(node_id, output_enable) << MCHP_XEC_OUT_EN_POS) | \
|
||||
(DT_PROP(node_id, output_high) << MCHP_XEC_OUT_HI_POS) | \
|
||||
(DT_PROP(node_id, output_low) << MCHP_XEC_OUT_LO_POS) | \
|
||||
(DT_PROP(node_id, low_power_enable) << MCHP_XEC_PIN_LOW_POWER_POS) | \
|
||||
(DT_PROP(node_id, microchip_output_func_invert) << MCHP_XEC_FUNC_INV_POS) | \
|
||||
(DT_ENUM_IDX_OR(node_id, slew_rate, 0x3) << MCHP_XEC_SLEW_RATE_POS) | \
|
||||
(DT_ENUM_IDX_OR(node_id, drive_strength, 0x7) << MCHP_XEC_DRV_STR_POS))
|
||||
#else
|
||||
#define Z_PINCTRL_STATE_PINCFG_INIT(node_id) \
|
||||
((DT_PROP(node_id, bias_disable) << MCHP_XEC_NO_PUD_POS) | \
|
||||
(DT_PROP(node_id, bias_pull_down) << MCHP_XEC_PD_POS) | \
|
||||
(DT_PROP(node_id, bias_pull_up) << MCHP_XEC_PU_POS) | \
|
||||
(DT_PROP(node_id, drive_push_pull) << MCHP_XEC_PUSH_PULL_POS) | \
|
||||
(DT_PROP(node_id, drive_open_drain) << MCHP_XEC_OPEN_DRAIN_POS) | \
|
||||
(DT_PROP(node_id, output_disable) << MCHP_XEC_OUT_DIS_POS) | \
|
||||
(DT_PROP(node_id, output_enable) << MCHP_XEC_OUT_EN_POS) | \
|
||||
(DT_PROP(node_id, output_high) << MCHP_XEC_OUT_HI_POS) | \
|
||||
(DT_PROP(node_id, output_low) << MCHP_XEC_OUT_LO_POS) | \
|
||||
(DT_PROP(node_id, low_power_enable) << MCHP_XEC_PIN_LOW_POWER_POS) | \
|
||||
(DT_PROP(node_id, microchip_output_func_invert) << MCHP_XEC_FUNC_INV_POS) | \
|
||||
(DT_ENUM_IDX(node_id, slew_rate) << MCHP_XEC_SLEW_RATE_POS) | \
|
||||
(DT_ENUM_IDX(node_id, drive_strength) << MCHP_XEC_DRV_STR_POS))
|
||||
#endif
|
||||
|
||||
/* initialize pin structure members */
|
||||
#define Z_PINCTRL_STATE_PIN_INIT(node_id, state_prop, idx) \
|
||||
(Z_PINCTRL_MCHP_XEC_PINMUX_INIT(DT_PROP_BY_IDX(node_id, state_prop, idx)) \
|
||||
| Z_PINCTRL_STATE_PINCFG_INIT(DT_PROP_BY_IDX(node_id, state_prop, idx))),
|
||||
#define Z_PINCTRL_STATE_PIN_INIT(node_id, state_prop, idx) \
|
||||
(Z_PINCTRL_MCHP_XEC_PINMUX_INIT(DT_PROP_BY_IDX(node_id, state_prop, idx)) | \
|
||||
Z_PINCTRL_STATE_PINCFG_INIT(DT_PROP_BY_IDX(node_id, state_prop, idx))),
|
||||
|
||||
/* Use DT FOREACH macro to initialize each used pin */
|
||||
#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \
|
||||
#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \
|
||||
{DT_FOREACH_PROP_ELEM(node_id, prop, Z_PINCTRL_STATE_PIN_INIT)}
|
||||
|
||||
/** @endcond */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue