Skip to content

Commit 715adcc

Browse files
AzharMCHPjhedberg
authored andcommitted
drivers: pinctrl: microchip: add pinctrl driver for Port G1 IP
Add pinctrl driver for Microchip Port G1 Peripheral IPs Signed-off-by: Mohamed Azhar <[email protected]>
1 parent a803182 commit 715adcc

File tree

7 files changed

+318
-0
lines changed

7 files changed

+318
-0
lines changed

drivers/pinctrl/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ zephyr_library_sources_ifdef(CONFIG_PINCTRL_SAM0 pinctrl_sam0.c)
2323
zephyr_library_sources_ifdef(CONFIG_PINCTRL_SAM_PIO4 pinctrl_sam_pio4.c)
2424
zephyr_library_sources_ifdef(CONFIG_PINCTRL_STM32 pinctrl_stm32.c)
2525
zephyr_library_sources_ifdef(CONFIG_PINCTRL_NXP_PORT pinctrl_nxp_port.c)
26+
zephyr_library_sources_ifdef(CONFIG_PINCTRL_MCHP_PORT_G1 pinctrl_mchp_port_g1.c)
2627
zephyr_library_sources_ifdef(CONFIG_PINCTRL_MCHP_XEC pinctrl_mchp_xec.c)
2728
zephyr_library_sources_ifdef(CONFIG_PINCTRL_IMX pinctrl_imx.c)
2829
zephyr_library_sources_ifdef(CONFIG_PINCTRL_SIFIVE pinctrl_sifive.c)

drivers/pinctrl/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ source "drivers/pinctrl/Kconfig.it8xxx2"
4646
source "drivers/pinctrl/Kconfig.npcx"
4747
source "drivers/pinctrl/Kconfig.numicro"
4848
source "drivers/pinctrl/Kconfig.nrf"
49+
source "drivers/pinctrl/Kconfig.mchp"
4950
source "drivers/pinctrl/Kconfig.mspm0"
5051
source "drivers/pinctrl/Kconfig.rpi_pico"
5152
source "drivers/pinctrl/Kconfig.sam"

drivers/pinctrl/Kconfig.mchp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright (c) 2025 Microchip Technology Inc.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config PINCTRL_MCHP_PORT_G1
5+
bool "Microchip PORT G1 pin controller driver"
6+
default y
7+
depends on DT_HAS_MICROCHIP_PORT_G1_PINCTRL_ENABLED
8+
help
9+
This option enables PINCTRL driver for group (g1) of PORT peripherals.
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/*
2+
* Copyright (c) 2025 Microchip Technology Inc.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/**
8+
* @file pinctrl_mchp_port_g1.c
9+
* @brief Pin control driver for Microchip devices.
10+
*
11+
* This file provides the implementation of pin control functions
12+
* for Microchip-based systems.
13+
*/
14+
15+
#include <zephyr/drivers/pinctrl.h>
16+
#include <soc.h>
17+
18+
/**
19+
* @brief Utility macro that expands to the PORT address if it exists.
20+
*
21+
* This macro checks if a node label exists in the device tree and, if it does,
22+
* it expands to the register address of that node label. If the node label does
23+
* not exist, it expands to nothing.
24+
*
25+
* @param nodelabel The node label to check in the device tree.
26+
*/
27+
/* clang-format off */
28+
#define MCHP_PORT_ADDR_OR_NONE(nodelabel) \
29+
IF_ENABLED(DT_NODE_EXISTS(DT_NODELABEL(nodelabel)), \
30+
(DT_REG_ADDR(DT_NODELABEL(nodelabel))))
31+
/* clang-format on */
32+
33+
/**
34+
* @brief Array of port addresses for the MCHP SAMD5x_E5x series.
35+
*
36+
* This array contains the register addresses of the ports (PORTA, PORTB, PORTC, and PORTD)
37+
* for the MCHP SAMD5x_E5x series microcontrollers. The addresses are obtained using the
38+
* MCHP_PORT_ADDR_OR_NONE macro, which ensures that only existing ports are included.
39+
* This can be updated for other devices using conditional comiplation directives
40+
*/
41+
static const uint32_t mchp_port_addrs[] = {
42+
MCHP_PORT_ADDR_OR_NONE(porta),
43+
MCHP_PORT_ADDR_OR_NONE(portb),
44+
MCHP_PORT_ADDR_OR_NONE(portc),
45+
MCHP_PORT_ADDR_OR_NONE(portd),
46+
};
47+
48+
/**
49+
* @brief Set pinmux registers using odd/even logic
50+
*
51+
* This function configures the pinmux registers for a given pin based on
52+
* the provided pin control information. It determines whether the pin number
53+
* is odd or even and sets the appropriate bits in the PORT_PMUX register.
54+
*
55+
* @param pin Pointer to the pin control information
56+
* @param reg Pointer to the base address of the port group registers
57+
*/
58+
static void pinctrl_pinmux(const pinctrl_soc_pin_t *pin)
59+
{
60+
port_group_registers_t *pRegister;
61+
62+
uint8_t pin_num = MCHP_PINMUX_PIN_GET(pin->pinmux);
63+
uint8_t port_id = MCHP_PINMUX_PORT_GET(pin->pinmux);
64+
uint8_t pin_mux = MCHP_PINMUX_PERIPH_GET(pin->pinmux);
65+
66+
bool is_odd = pin_num & 1;
67+
uint32_t idx = pin_num / 2U;
68+
69+
pRegister = (port_group_registers_t *)mchp_port_addrs[port_id];
70+
71+
if (pRegister != NULL) {
72+
/* Each pinmux register holds the config for two pins. The
73+
* even numbered pin goes in the bits 0..3 and the odd
74+
* numbered pin in bits 4..7.
75+
*/
76+
if (is_odd == true) {
77+
pRegister->PORT_PMUX[idx] |= PORT_PMUX_PMUXO(pin_mux);
78+
} else {
79+
pRegister->PORT_PMUX[idx] |= PORT_PMUX_PMUXE(pin_mux);
80+
}
81+
pRegister->PORT_PINCFG[pin_num] |= (uint8_t)PORT_PINCFG_PMUXEN_Msk;
82+
}
83+
}
84+
85+
/**
86+
* @brief Set all pin configuration registers by checking the flags
87+
*
88+
* This function configures various pin settings such as pull-up, pull-down,
89+
* input enable, output enable, and drive strength based on the provided
90+
* pin control information.
91+
*
92+
* @param pin Pointer to the pin control information
93+
* @param reg Pointer to the base address of the port group registers
94+
*/
95+
static void pinctrl_set_flags(const pinctrl_soc_pin_t *pin)
96+
{
97+
port_group_registers_t *pRegister;
98+
99+
uint8_t pin_num = MCHP_PINMUX_PIN_GET(pin->pinmux);
100+
uint8_t port_id = MCHP_PINMUX_PORT_GET(pin->pinmux);
101+
102+
pRegister = (port_group_registers_t *)mchp_port_addrs[port_id];
103+
104+
if (pRegister != NULL) {
105+
106+
/* Check if pull-up or pull-down resistors need to be configured */
107+
if (((pin->pinflag & MCHP_PINCTRL_PULLUP) != 0) ||
108+
((pin->pinflag & MCHP_PINCTRL_PULLDOWN) != 0)) {
109+
if ((pin->pinflag & MCHP_PINCTRL_PULLUP) != 0) {
110+
/* If pull-up resistor enabled,
111+
* set the corresponding bit in PORT_OUT reg
112+
*/
113+
pRegister->PORT_OUT |= (1 << pin_num);
114+
}
115+
pRegister->PORT_PINCFG[pin_num] |= PORT_PINCFG_PULLEN(1);
116+
} else {
117+
pRegister->PORT_PINCFG[pin_num] &= ~PORT_PINCFG_PULLEN(1);
118+
}
119+
120+
/* if input is enabled, set the corresponding bit in PORT_PINCFG register */
121+
if ((pin->pinflag & MCHP_PINCTRL_INPUTENABLE) != 0) {
122+
pRegister->PORT_PINCFG[pin_num] |= PORT_PINCFG_INEN(1);
123+
} else {
124+
pRegister->PORT_PINCFG[pin_num] &= ~PORT_PINCFG_INEN(1);
125+
}
126+
127+
/* if output is enabled, set the corresponding bit in PORT_DIR register */
128+
if ((pin->pinflag & MCHP_PINCTRL_OUTPUTENABLE) != 0) {
129+
pRegister->PORT_DIR |= (1 << pin_num);
130+
} else {
131+
pRegister->PORT_DIR &= ~(1 << pin_num);
132+
}
133+
134+
/* if drive strength is enabled, set the corresponding bit in PORT_PINCFG reg */
135+
if ((pin->pinflag & MCHP_PINCTRL_DRIVESTRENGTH) != 0) {
136+
pRegister->PORT_PINCFG[pin_num] |= PORT_PINCFG_DRVSTR(1);
137+
} else {
138+
pRegister->PORT_PINCFG[pin_num] &= ~PORT_PINCFG_DRVSTR(1);
139+
}
140+
}
141+
}
142+
143+
/**
144+
* @brief Configure a specific pin based on the provided pin configuration.
145+
*
146+
* This helper function configures a pin by determining its port function and then
147+
* calling the appropriate functions to set the pinmux and other pin configurations.
148+
*
149+
* @param pin The pin configuration to be applied. This is of type pinctrl_soc_pin_t.
150+
*/
151+
static void pinctrl_configure_pin(pinctrl_soc_pin_t pin)
152+
{
153+
uint8_t port_func = MCHP_PINMUX_FUNC_GET(pin.pinmux);
154+
155+
/* call pinmux function if alternate function is configured */
156+
if (port_func == MCHP_PINMUX_FUNC_periph) {
157+
pinctrl_pinmux(&pin);
158+
}
159+
160+
/* set all other pin configurations */
161+
pinctrl_set_flags(&pin);
162+
}
163+
164+
/**
165+
* @brief Configure multiple pins.
166+
*
167+
* This function configures a set of pins based on the provided pin
168+
* configuration array.
169+
*
170+
* @param pins Pointer to an array of pinctrl_soc_pin_t structures that
171+
* define the pin configurations.
172+
* @param pin_cnt Number of pins to configure.
173+
* @param reg Unused parameter.
174+
*
175+
* @return 0 on success.
176+
*/
177+
int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg)
178+
{
179+
ARG_UNUSED(reg);
180+
181+
for (uint8_t i = 0U; i < pin_cnt; i++) {
182+
pinctrl_configure_pin(*pins);
183+
pins++;
184+
}
185+
186+
return 0;
187+
}

soc/microchip/sam/sam_d5x_e5x/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33

44
set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "")
55

6+
zephyr_include_directories(common)
67
zephyr_include_directories(${SOC_SERIES})

soc/microchip/sam/sam_d5x_e5x/Kconfig.soc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,15 @@ config SOC_FAMILY_MICROCHIP_SAM_D5X_E5X
77
config SOC_FAMILY
88
default "microchip_sam_d5x_e5x" if SOC_FAMILY_MICROCHIP_SAM_D5X_E5X
99

10+
# List of Peripheral IPs available in SOC_FAMILY_MICROCHIP_SAM_D5X_E5X family
11+
if SOC_FAMILY_MICROCHIP_SAM_D5X_E5X
12+
13+
config PINCTRL_MCHP_PORT_U2210_2_2_0
14+
bool
15+
default y
16+
help
17+
Enable PORT pinctrl peripheral IP version 2.2.0 (U2210).
18+
19+
endif # SOC_FAMILY_MICROCHIP_SAM_D5X_E5X
20+
1021
rsource "*/Kconfig.soc"
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
* Copyright (c) 2025 Microchip Technology Inc.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef SOC_MICROCHIP_SAM_D5X_E5X_COMMON_PINCTRL_SOC_H_
8+
#define SOC_MICROCHIP_SAM_D5X_E5X_COMMON_PINCTRL_SOC_H_
9+
10+
#include <zephyr/devicetree.h>
11+
#include <zephyr/types.h>
12+
#include "dt-bindings/sam/sam_d5x_e5x/common/mchp_pinctrl_pinmux_sam.h"
13+
14+
#ifdef __cplusplus
15+
extern "C" {
16+
#endif
17+
18+
/** @cond INTERNAL_HIDDEN */
19+
20+
/**
21+
* @brief Structure representing the pin control settings for a SOC pin.
22+
*
23+
* This structure is used to define the pinmux and pin configuration settings
24+
* for a specific pin on the SOC. It includes information about the port, pin,
25+
* function, bias, drive, and other configuration options.
26+
*/
27+
typedef struct pinctrl_soc_pin {
28+
/** Pinmux settings (port, pin and function). */
29+
uint16_t pinmux;
30+
/** Pin configuration (bias, drive etc). */
31+
uint16_t pinflag;
32+
} pinctrl_soc_pin_t;
33+
34+
/**
35+
* @brief Utility macro to initialize pinmux field.
36+
*
37+
* @param node_id Node identifier.
38+
*/
39+
#define Z_PINCTRL_MCHP_PINMUX_INIT(node_id, prop, idx) DT_PROP_BY_IDX(node_id, prop, idx)
40+
41+
/**
42+
* @brief Utility macro to initialize each pin.
43+
*
44+
* @param node_id Node identifier.
45+
* @param prop Property name.
46+
* @param idx Property entry index.
47+
*/
48+
#define Z_PINCTRL_MCHP_PINFLAG_INIT(node_id, prop, idx) \
49+
((DT_PROP(node_id, bias_pull_up) << MCHP_PINCTRL_PULLUP_POS) | \
50+
(DT_PROP(node_id, bias_pull_down) << MCHP_PINCTRL_PULLDOWN_POS) | \
51+
(DT_PROP(node_id, input_enable) << MCHP_PINCTRL_INPUTENABLE_POS) | \
52+
(DT_PROP(node_id, output_enable) << MCHP_PINCTRL_OUTPUTENABLE_POS) | \
53+
(DT_ENUM_IDX(node_id, drive_strength) << MCHP_PINCTRL_DRIVESTRENGTH_POS)),
54+
55+
/**
56+
* @brief Utility macro to initialize each pin.
57+
*
58+
* @param node_id Node identifier.
59+
* @param prop Property name.
60+
* @param idx Property entry index.
61+
*/
62+
#define Z_PINCTRL_STATE_PIN_INIT(node_id, prop, idx) \
63+
{.pinmux = Z_PINCTRL_MCHP_PINMUX_INIT(node_id, prop, idx), \
64+
.pinflag = Z_PINCTRL_MCHP_PINFLAG_INIT(node_id, prop, idx)},
65+
66+
/**
67+
* @brief Utility macro to initialize state pins contained in a given property.
68+
*
69+
* @param node_id Node identifier.
70+
* @param prop Property name describing state pins.
71+
*/
72+
#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \
73+
{DT_FOREACH_CHILD_VARGS(DT_PHANDLE(node_id, prop), DT_FOREACH_PROP_ELEM, pinmux, \
74+
Z_PINCTRL_STATE_PIN_INIT)}
75+
76+
/** @endcond */
77+
78+
/**
79+
* @brief Pin flags/attributes
80+
* @anchor MCHP_PINFLAGS
81+
*
82+
* @{
83+
*/
84+
85+
#define MCHP_PINCTRL_FLAGS_DEFAULT (0U)
86+
#define MCHP_PINCTRL_FLAGS_POS (0U)
87+
#define MCHP_PINCTRL_FLAGS_MASK (0x3F << MCHP_PINCTRL_FLAGS_POS)
88+
#define MCHP_PINCTRL_FLAG_MASK (1U)
89+
#define MCHP_PINCTRL_PULLUP_POS (MCHP_PINCTRL_FLAGS_POS)
90+
#define MCHP_PINCTRL_PULLUP (1U << MCHP_PINCTRL_PULLUP_POS)
91+
#define MCHP_PINCTRL_PULLDOWN_POS (MCHP_PINCTRL_PULLUP_POS + 1U)
92+
#define MCHP_PINCTRL_PULLDOWN (1U << MCHP_PINCTRL_PULLDOWN_POS)
93+
#define MCHP_PINCTRL_OPENDRAIN_POS (MCHP_PINCTRL_PULLDOWN_POS + 1U)
94+
#define MCHP_PINCTRL_OPENDRAIN (1U << MCHP_PINCTRL_OPENDRAIN_POS)
95+
#define MCHP_PINCTRL_INPUTENABLE_POS (MCHP_PINCTRL_OPENDRAIN_POS + 1U)
96+
#define MCHP_PINCTRL_INPUTENABLE (1U << MCHP_PINCTRL_INPUTENABLE_POS)
97+
#define MCHP_PINCTRL_OUTPUTENABLE_POS (MCHP_PINCTRL_INPUTENABLE_POS + 1U)
98+
#define MCHP_PINCTRL_OUTPUTENABLE (1U << MCHP_PINCTRL_OUTPUTENABLE_POS)
99+
#define MCHP_PINCTRL_DRIVESTRENGTH_POS (MCHP_PINCTRL_OUTPUTENABLE_POS + 1U)
100+
#define MCHP_PINCTRL_DRIVESTRENGTH (1U << MCHP_PINCTRL_DRIVESTRENGTH_POS)
101+
102+
/** @} */
103+
104+
#ifdef __cplusplus
105+
}
106+
#endif
107+
108+
#endif /* SOC_MICROCHIP_SAM_D5X_E5X_COMMON_PINCTRL_SOC_H_ */

0 commit comments

Comments
 (0)