Skip to content

Commit 4fa5fc3

Browse files
scottwcpgcarlescufi
authored andcommitted
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 <[email protected]>
1 parent d12de2d commit 4fa5fc3

File tree

7 files changed

+337
-18
lines changed

7 files changed

+337
-18
lines changed

drivers/pinctrl/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,6 @@ zephyr_library_sources_ifdef(CONFIG_PINCTRL_ENE_KB1200 pinctrl_ene_kb1200.c)
3939
zephyr_library_sources_ifdef(CONFIG_PINCTRL_IMX_SCU pinctrl_imx_scu.c)
4040
zephyr_library_sources_ifdef(CONFIG_PINCTRL_MAX32 pinctrl_max32.c)
4141
zephyr_library_sources_ifdef(CONFIG_PINCTRL_IMX_SCMI pinctrl_imx_scmi.c)
42+
zephyr_library_sources_ifdef(CONFIG_PINCTRL_MCHP_MEC5 pinctrl_mchp_mec5.c)
4243

4344
add_subdirectory(renesas)

drivers/pinctrl/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ source "drivers/pinctrl/Kconfig.mci_io_mux"
6666
source "drivers/pinctrl/Kconfig.ene"
6767
source "drivers/pinctrl/Kconfig.zynqmp"
6868
source "drivers/pinctrl/Kconfig.max32"
69+
source "drivers/pinctrl/Kconfig.mec5"
6970

7071
rsource "renesas/Kconfig"
7172

drivers/pinctrl/Kconfig.mec5

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright (c) 2024 Microchip Technology Inc.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config PINCTRL_MCHP_MEC5
5+
bool "Pin controller driver for MCHP MEC5 MCUs"
6+
default y
7+
depends on DT_HAS_MICROCHIP_MEC5_PINCTRL_ENABLED
8+
help
9+
Enable pin controller driver for Microchip MEC5 MCUs

drivers/pinctrl/pinctrl_mchp_mec5.c

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
/*
2+
* Copyright (c) 2016 Open-RnD Sp. z o.o.
3+
* Copyright (c) 2021 Linaro Limited
4+
* Copyright (c) 2021 Nordic Semiconductor ASA
5+
* Copyright (c) 2024 Microchip Technology Inc.
6+
*
7+
* SPDX-License-Identifier: Apache-2.0
8+
*/
9+
10+
#define DT_DRV_COMPAT microchip_mec5_pinctrl
11+
12+
#include <zephyr/drivers/pinctrl.h>
13+
#include <zephyr/dt-bindings/pinctrl/mchp-xec-pinctrl.h>
14+
#include <mec_gpio_api.h>
15+
16+
static const struct mec_gpio_props cfg1[] = {
17+
{MEC_GPIO_OSEL_PROP_ID, MEC_GPIO_PROP_OSEL_CTRL},
18+
{MEC_GPIO_INPAD_DIS_PROP_ID, MEC_GPIO_PROP_INPAD_EN},
19+
};
20+
21+
/* DT enable booleans take precedence over disable booleans.
22+
* We initially clear alternate output disable allowing us to set output state
23+
* in the control register. Hardware sets output state bit in both control and
24+
* parallel output register bits. Alternate output disable only controls which
25+
* register bit is writable by the EC. We also clear the input pad disable
26+
* bit because we need the input pin state and we don't know if the requested
27+
* alternate function is input or bi-directional.
28+
* Note 1: hardware allows input and output to be simultaneously enabled.
29+
* Note 2: hardware interrupt detection is only on the input path.
30+
*/
31+
static int mec5_config_pin(uint32_t pinmux, uint32_t altf)
32+
{
33+
uint32_t conf = pinmux;
34+
uint32_t pin = 0, temp = 0;
35+
int ret = 0;
36+
size_t idx = 0;
37+
struct mec_gpio_props cfg2[12];
38+
39+
ret = mec_hal_gpio_pin_num(MCHP_XEC_PINMUX_PORT(pinmux), MCHP_XEC_PINMUX_PIN(pinmux), &pin);
40+
if (ret) {
41+
return -EINVAL;
42+
}
43+
44+
ret = mec_hal_gpio_set_props(pin, cfg1, ARRAY_SIZE(cfg1));
45+
if (ret) {
46+
return -EIO;
47+
}
48+
49+
/* slew rate */
50+
temp = (conf >> MCHP_XEC_SLEW_RATE_POS) & MCHP_XEC_SLEW_RATE_MSK0;
51+
if (temp != MCHP_XEC_SLEW_RATE_MSK0) {
52+
cfg2[idx].prop = MEC_GPIO_SLEW_RATE_ID;
53+
cfg2[idx].val = (uint8_t)MEC_GPIO_SLEW_RATE_SLOW;
54+
if (temp == MCHP_XEC_SLEW_RATE_FAST0) {
55+
cfg2[idx].val = (uint8_t)MEC_GPIO_SLEW_RATE_FAST;
56+
}
57+
idx++;
58+
}
59+
60+
/* drive strength */
61+
temp = (conf >> MCHP_XEC_DRV_STR_POS) & MCHP_XEC_DRV_STR_MSK0;
62+
if (temp != MCHP_XEC_DRV_STR_MSK0) {
63+
cfg2[idx].prop = MEC_GPIO_DRV_STR_ID;
64+
cfg2[idx].val = (uint8_t)(temp - 1u);
65+
idx++;
66+
}
67+
68+
/* Touch internal pull-up/pull-down? */
69+
cfg2[idx].prop = MEC_GPIO_PUD_PROP_ID;
70+
if (conf & BIT(MCHP_XEC_NO_PUD_POS)) {
71+
cfg2[idx++].val = MEC_GPIO_PROP_NO_PUD;
72+
} else if (conf & BIT(MCHP_XEC_PU_POS)) {
73+
cfg2[idx++].val = MEC_GPIO_PROP_PULL_UP;
74+
} else if (conf & BIT(MCHP_XEC_PD_POS)) {
75+
cfg2[idx++].val = MEC_GPIO_PROP_PULL_DN;
76+
}
77+
78+
/* Touch output enable. We always enable input */
79+
if (conf & (BIT(MCHP_XEC_OUT_DIS_POS) | BIT(MCHP_XEC_OUT_EN_POS))) {
80+
cfg2[idx].prop = MEC_GPIO_DIR_PROP_ID;
81+
cfg2[idx].val = MEC_GPIO_PROP_DIR_IN;
82+
if (conf & BIT(MCHP_XEC_OUT_EN_POS)) {
83+
cfg2[idx].val = MEC_GPIO_PROP_DIR_OUT;
84+
}
85+
idx++;
86+
}
87+
88+
/* Touch output state? Bit can be set even if the direction is input only */
89+
if (conf & (BIT(MCHP_XEC_OUT_LO_POS) | BIT(MCHP_XEC_OUT_HI_POS))) {
90+
cfg2[idx].prop = MEC_GPIO_CTRL_OUT_VAL_ID;
91+
cfg2[idx].val = 0u;
92+
if (conf & BIT(MCHP_XEC_OUT_HI_POS)) {
93+
cfg2[idx].val = 1u;
94+
}
95+
idx++;
96+
}
97+
98+
/* Touch output buffer type? */
99+
if (conf & (BIT(MCHP_XEC_PUSH_PULL_POS) | BIT(MCHP_XEC_OPEN_DRAIN_POS))) {
100+
cfg2[idx].prop = MEC_GPIO_OBUFT_PROP_ID;
101+
cfg2[idx].val = MEC_GPIO_PROP_PUSH_PULL;
102+
if (conf & BIT(MCHP_XEC_OPEN_DRAIN_POS)) {
103+
cfg2[idx].val = MEC_GPIO_PROP_OPEN_DRAIN;
104+
}
105+
idx++;
106+
}
107+
108+
/* Always touch power gate */
109+
cfg2[idx].prop = MEC_GPIO_PWRGT_PROP_ID;
110+
cfg2[idx].val = MEC_GPIO_PROP_PWRGT_VTR;
111+
if (conf & BIT(MCHP_XEC_PIN_LOW_POWER_POS)) {
112+
cfg2[idx].val = MEC_GPIO_PROP_PWRGT_OFF;
113+
}
114+
idx++;
115+
116+
/* Always touch MUX (alternate function) */
117+
cfg2[idx].prop = MEC_GPIO_MUX_PROP_ID;
118+
cfg2[idx].val = (uint8_t)altf;
119+
idx++;
120+
121+
/* Always touch invert of alternate function. Need another bit to avoid touching */
122+
cfg2[idx].prop = MEC_GPIO_FUNC_POL_PROP_ID;
123+
cfg2[idx].val = MEC_GPIO_PROP_FUNC_OUT_NON_INV;
124+
if (conf & BIT(MCHP_XEC_FUNC_INV_POS)) {
125+
cfg2[idx].val = MEC_GPIO_PROP_FUNC_OUT_INV;
126+
}
127+
idx++;
128+
129+
/* HW sets output state set in control & parallel regs */
130+
ret = mec_hal_gpio_set_props(pin, cfg2, idx);
131+
if (ret) {
132+
return -EIO;
133+
}
134+
135+
/* make output state in control read-only in control and read-write in parallel reg */
136+
ret = mec_hal_gpio_set_property(pin, MEC_GPIO_OSEL_PROP_ID, MEC_GPIO_PROP_OSEL_PAROUT);
137+
if (ret) {
138+
return -EIO;
139+
}
140+
141+
return 0;
142+
}
143+
144+
int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg)
145+
{
146+
uint32_t pinmux, func;
147+
int ret;
148+
149+
ARG_UNUSED(reg);
150+
151+
for (uint8_t i = 0U; i < pin_cnt; i++) {
152+
pinmux = pins[i];
153+
154+
func = MCHP_XEC_PINMUX_FUNC(pinmux);
155+
if (func >= MCHP_AFMAX) {
156+
return -EINVAL;
157+
}
158+
159+
ret = mec5_config_pin(pinmux, func);
160+
if (ret < 0) {
161+
return ret;
162+
}
163+
}
164+
165+
return 0;
166+
}

dts/arm/microchip/mec5.dtsi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@
136136
};
137137
};
138138
pinctrl: pin-controller@40081000 {
139+
compatible = "microchip,mec5-pinctrl";
139140
#address-cells = <1>;
140141
#size-cells = <1>;
141142
reg = <0x40081000 0x1000>;
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# Copyright (c) 2024 Microchip Technology Inc.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: |
5+
Microchip XEC Pin controller Node
6+
Based on pincfg-node.yaml binding.
7+
The MCHP XEC pin controller is a singleton node responsible for controlling
8+
pin function selection and pin properties. For example, you can use this
9+
node to select peripheral pin functions.
10+
11+
The node has the 'pinctrl' node label set in your SoC's devicetree,
12+
so you can modify it like this:
13+
14+
&pinctrl {
15+
/* your modifications go here */
16+
};
17+
18+
All device pin configurations should be placed in child nodes of the
19+
'pinctrl' node, as in the spi0 example shown at the end:
20+
21+
A group can also specify shared pin properties common to all the specified
22+
pins, such as the 'bias-pull-up' property in group 2. Here is a list of
23+
supported standard pin properties:
24+
25+
- bias-disable: Disable pull-up/down (default behavior, not required).
26+
- bias-pull-down: Enable pull-down resistor.
27+
- bias-pull-up: Enable pull-up resistor.
28+
- drive-push-pull: Output driver is push-pull (default, not required).
29+
- drive-open-drain: Output driver is open-drain.
30+
- output-high: Set output state high when pin configured.
31+
- output-low: Set output state low when pin configured.
32+
33+
Custom pin properties for drive strength and slew rate are available:
34+
- drive-strength
35+
- slew-rate
36+
37+
Driver strength and slew rate hardware defaults vary by SoC and pin.
38+
39+
An example for MEC174x family, include the chip level pinctrl
40+
DTSI file in the board level DTS:
41+
42+
#include <microchip/mec5/mec1743qlj-a0-pinctrl.dtsi>
43+
44+
We want to use the shared SPI port of the MEC172x QMSPI controller
45+
and want the chip select 0 to be open-drain.
46+
47+
To change a pin's pinctrl default properties add a reference to the
48+
pin in the board's DTS file and set the properties.
49+
50+
&spi0 {
51+
pinctrl-0 = < &shd_cs0_n_gpio055
52+
&shd_clk_gpio056
53+
&shd_io0_gpio223
54+
&shd_io1_gpio224
55+
&shd_io3_gpio016 >;
56+
pinctrl-names = "default";
57+
}
58+
59+
&shd_cs0_n_gpio055 {
60+
drive-open-drain;
61+
};
62+
63+
compatible: "microchip,mec5-pinctrl"
64+
65+
include: base.yaml
66+
67+
properties:
68+
reg:
69+
required: true
70+
71+
child-binding:
72+
description: |
73+
This binding gives a base representation of the Microchip XEC pins
74+
configuration
75+
76+
include:
77+
- name: pincfg-node.yaml
78+
property-allowlist:
79+
- bias-disable
80+
- bias-pull-down
81+
- bias-pull-up
82+
- drive-push-pull
83+
- drive-open-drain
84+
- low-power-enable
85+
- output-disable
86+
- output-enable
87+
- output-high
88+
- output-low
89+
90+
properties:
91+
pinmux:
92+
type: int
93+
required: true
94+
description: Pinmux selection
95+
96+
slew-rate:
97+
type: string
98+
enum:
99+
- "low-speed"
100+
- "high-speed"
101+
description: |
102+
Pin speed. The default value of slew-rate is the SoC power-on-reset
103+
value. Please refer to the data sheet as a small number of pins
104+
may have a different default and some pins do not implement
105+
slew rate adjustment.
106+
107+
drive-strength:
108+
type: string
109+
enum:
110+
- "1x"
111+
- "2x"
112+
- "4x"
113+
- "6x"
114+
description: |
115+
Pin output drive strength for PIO and PIO-24 pin types. Default
116+
is "1x" for most pins. PIO pins are 2, 4, 8, or 12 mA. PIO-24 pins
117+
are 4, 8, 16, or 24 mA. Please refer to the data sheet for each
118+
pin's PIO type and default drive strength.
119+
120+
microchip,output-func-invert:
121+
type: boolean
122+
description:
123+
Invert polarity of an output alternate function. Input functions
124+
are not affected.

soc/microchip/mec/common/pinctrl_soc.h

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,28 +31,45 @@ typedef uint32_t pinctrl_soc_pin_t;
3131
/* initialize pinmux member fields of pinctrl_pin_t */
3232
#define Z_PINCTRL_MCHP_XEC_PINMUX_INIT(node_id) (uint32_t)(DT_PROP(node_id, pinmux))
3333

34-
#define Z_PINCTRL_STATE_PINCFG_INIT(node_id) \
35-
((DT_PROP(node_id, bias_disable) << MCHP_XEC_NO_PUD_POS) \
36-
| (DT_PROP(node_id, bias_pull_down) << MCHP_XEC_PD_POS) \
37-
| (DT_PROP(node_id, bias_pull_up) << MCHP_XEC_PU_POS) \
38-
| (DT_PROP(node_id, drive_push_pull) << MCHP_XEC_PUSH_PULL_POS) \
39-
| (DT_PROP(node_id, drive_open_drain) << MCHP_XEC_OPEN_DRAIN_POS) \
40-
| (DT_PROP(node_id, output_disable) << MCHP_XEC_OUT_DIS_POS) \
41-
| (DT_PROP(node_id, output_enable) << MCHP_XEC_OUT_EN_POS) \
42-
| (DT_PROP(node_id, output_high) << MCHP_XEC_OUT_HI_POS) \
43-
| (DT_PROP(node_id, output_low) << MCHP_XEC_OUT_LO_POS) \
44-
| (DT_PROP(node_id, low_power_enable) << MCHP_XEC_PIN_LOW_POWER_POS) \
45-
| (DT_PROP(node_id, microchip_output_func_invert) << MCHP_XEC_FUNC_INV_POS) \
46-
| (DT_ENUM_IDX(node_id, slew_rate) << MCHP_XEC_SLEW_RATE_POS) \
47-
| (DT_ENUM_IDX(node_id, drive_strength) << MCHP_XEC_DRV_STR_POS))
34+
#ifdef CONFIG_HAS_MEC5_HAL
35+
#define Z_PINCTRL_STATE_PINCFG_INIT(node_id) \
36+
((DT_PROP(node_id, bias_disable) << MCHP_XEC_NO_PUD_POS) | \
37+
(DT_PROP(node_id, bias_pull_down) << MCHP_XEC_PD_POS) | \
38+
(DT_PROP(node_id, bias_pull_up) << MCHP_XEC_PU_POS) | \
39+
(DT_PROP(node_id, drive_push_pull) << MCHP_XEC_PUSH_PULL_POS) | \
40+
(DT_PROP(node_id, drive_open_drain) << MCHP_XEC_OPEN_DRAIN_POS) | \
41+
(DT_PROP(node_id, output_disable) << MCHP_XEC_OUT_DIS_POS) | \
42+
(DT_PROP(node_id, output_enable) << MCHP_XEC_OUT_EN_POS) | \
43+
(DT_PROP(node_id, output_high) << MCHP_XEC_OUT_HI_POS) | \
44+
(DT_PROP(node_id, output_low) << MCHP_XEC_OUT_LO_POS) | \
45+
(DT_PROP(node_id, low_power_enable) << MCHP_XEC_PIN_LOW_POWER_POS) | \
46+
(DT_PROP(node_id, microchip_output_func_invert) << MCHP_XEC_FUNC_INV_POS) | \
47+
(DT_ENUM_IDX_OR(node_id, slew_rate, 0x3) << MCHP_XEC_SLEW_RATE_POS) | \
48+
(DT_ENUM_IDX_OR(node_id, drive_strength, 0x7) << MCHP_XEC_DRV_STR_POS))
49+
#else
50+
#define Z_PINCTRL_STATE_PINCFG_INIT(node_id) \
51+
((DT_PROP(node_id, bias_disable) << MCHP_XEC_NO_PUD_POS) | \
52+
(DT_PROP(node_id, bias_pull_down) << MCHP_XEC_PD_POS) | \
53+
(DT_PROP(node_id, bias_pull_up) << MCHP_XEC_PU_POS) | \
54+
(DT_PROP(node_id, drive_push_pull) << MCHP_XEC_PUSH_PULL_POS) | \
55+
(DT_PROP(node_id, drive_open_drain) << MCHP_XEC_OPEN_DRAIN_POS) | \
56+
(DT_PROP(node_id, output_disable) << MCHP_XEC_OUT_DIS_POS) | \
57+
(DT_PROP(node_id, output_enable) << MCHP_XEC_OUT_EN_POS) | \
58+
(DT_PROP(node_id, output_high) << MCHP_XEC_OUT_HI_POS) | \
59+
(DT_PROP(node_id, output_low) << MCHP_XEC_OUT_LO_POS) | \
60+
(DT_PROP(node_id, low_power_enable) << MCHP_XEC_PIN_LOW_POWER_POS) | \
61+
(DT_PROP(node_id, microchip_output_func_invert) << MCHP_XEC_FUNC_INV_POS) | \
62+
(DT_ENUM_IDX(node_id, slew_rate) << MCHP_XEC_SLEW_RATE_POS) | \
63+
(DT_ENUM_IDX(node_id, drive_strength) << MCHP_XEC_DRV_STR_POS))
64+
#endif
4865

4966
/* initialize pin structure members */
50-
#define Z_PINCTRL_STATE_PIN_INIT(node_id, state_prop, idx) \
51-
(Z_PINCTRL_MCHP_XEC_PINMUX_INIT(DT_PROP_BY_IDX(node_id, state_prop, idx)) \
52-
| Z_PINCTRL_STATE_PINCFG_INIT(DT_PROP_BY_IDX(node_id, state_prop, idx))),
67+
#define Z_PINCTRL_STATE_PIN_INIT(node_id, state_prop, idx) \
68+
(Z_PINCTRL_MCHP_XEC_PINMUX_INIT(DT_PROP_BY_IDX(node_id, state_prop, idx)) | \
69+
Z_PINCTRL_STATE_PINCFG_INIT(DT_PROP_BY_IDX(node_id, state_prop, idx))),
5370

5471
/* Use DT FOREACH macro to initialize each used pin */
55-
#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \
72+
#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \
5673
{DT_FOREACH_PROP_ELEM(node_id, prop, Z_PINCTRL_STATE_PIN_INIT)}
5774

5875
/** @endcond */

0 commit comments

Comments
 (0)