drivers: pinctrl: add pinctrl driver for Arm mps2

Adds pinctrl driver for all Arm mps2 targets.

Signed-off-by: Samuel Chee <samche01@arm.com>
Signed-off-by: Sudan Landge <sudan.landge@arm.com>
This commit is contained in:
Samuel Chee 2025-02-05 13:54:33 +00:00 committed by Benjamin Cabé
commit 99ae4bf132
9 changed files with 328 additions and 2 deletions

View file

@ -96,8 +96,7 @@ static int gpio_cmsdk_ahb_port_toggle_bits(const struct device *dev,
return 0;
}
static int cmsdk_ahb_gpio_config(const struct device *dev, uint32_t mask,
gpio_flags_t flags)
int cmsdk_ahb_gpio_config(const struct device *dev, uint32_t mask, gpio_flags_t flags)
{
const struct gpio_cmsdk_ahb_cfg * const cfg = dev->config;

View file

@ -1,10 +1,12 @@
# Copyright (c) 2021 Nordic Semiconductor ASA
# Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
# SPDX-License-Identifier: Apache-2.0
zephyr_library()
zephyr_library_sources(common.c)
zephyr_library_sources_ifdef(CONFIG_PINCTRL_TELINK_B91 pinctrl_b91.c)
zephyr_library_sources_ifdef(CONFIG_PINCTRL_AMBIQ pinctrl_ambiq.c)
zephyr_library_sources_ifdef(CONFIG_PINCTRL_ARM_MPS2 pinctrl_arm_mps2.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)

View file

@ -1,4 +1,5 @@
# Copyright (c) 2021 Nordic Semiconductor ASA
# Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
# SPDX-License-Identifier: Apache-2.0
menuconfig PINCTRL
@ -35,6 +36,7 @@ config PINCTRL_DYNAMIC
source "drivers/pinctrl/Kconfig.b91"
source "drivers/pinctrl/Kconfig.ambiq"
source "drivers/pinctrl/Kconfig.arm_mps2"
source "drivers/pinctrl/Kconfig.gd32"
source "drivers/pinctrl/Kconfig.it8xxx2"
source "drivers/pinctrl/Kconfig.npcx"

View file

@ -0,0 +1,10 @@
# Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
# SPDX-License-Identifier: Apache-2.0
config PINCTRL_ARM_MPS2
bool "Arm MPS2 pin controller driver"
default y
depends on DT_HAS_ARM_MPS2_PINCTRL_ENABLED
help
Arm MPS2 pinctrl driver

View file

@ -0,0 +1,55 @@
/*
* Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "zephyr/device.h"
#include "zephyr/drivers/gpio.h"
#include <zephyr/drivers/pinctrl.h>
#include <zephyr/devicetree/gpio.h>
#include <zephyr/drivers/gpio/gpio_cmsdk_ahb.h>
/**
* The ARM MPS2 Board has 4 GPIO controllers. These controllers
* are responsible for pin muxing, input/output, pull-up, etc.
*
* All GPIO controller pins are exposed via the following sequence of pin
* numbers:
* Pins 0 - 15 are for GPIO0
* Pins 16 - 31 are for GPIO1
* Pins 32 - 47 are for GPIO2
* Pins 48 - 51 are for GPIO3
*
* For the GPIO controllers configuration ARM MPS2 Board follows the
* Arduino compliant pin out.
*/
static const struct device *const gpio_ports[] = {
DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpio0)),
DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpio1)),
DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpio2)),
DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpio3)),
};
static int pinctrl_configure_pin(const pinctrl_soc_pin_t *pin)
{
uint32_t flags = pin->input_enable ? GPIO_INPUT : GPIO_OUTPUT;
/* Each gpio has 16 pins, so divide by 16 to get specific gpio*/
const struct device *gpio_dev = gpio_ports[pin->pin_num >> 4];
return cmsdk_ahb_gpio_config(gpio_dev, pin->pin_num % 16, flags);
}
int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg)
{
ARG_UNUSED(reg);
for (uint8_t i = 0U; i < pin_cnt; i++) {
if (pinctrl_configure_pin(pins++) == -ENOTSUP) {
return -ENOTSUP;
}
}
return 0;
}

View file

@ -0,0 +1,81 @@
# Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
# SPDX-License-Identifier: Apache-2.0
description: |
The Arm Mps2 pin controller is a node responsible for controlling
pin function selection and pin properties, such as routing a UART3 TX
to pin 1.
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 shown in this example:
&pinctrl {
/* configuration for the usart0 "default" state */
uart3_default: uart3_default {
/* group 1 */
group1 {
/* configure P1 as UART3 TX */
pinmux = <UART3_TXD_EXP>;
};
/* group 2 */
group2 {
/* configure P0 as UART3 RX */
pinmux = <UART3_RXD_EXP>;
/* enable input on pin 1 */
input-enable;
};
};
};
The 'uart3_default' child node encodes the pin configurations for a
particular state of a device; in this case, the default (that is, active)
state.
As shown, pin configurations are organized in groups within each child node.
Each group can specify a list of pin function selections in the 'pinmux'
property. Here is a list of supported standard pin properties:
- input-enable
A group can also specify shared pin properties common to all the specified
pins, such as the 'input-enable' property in group 2.
To link pin configurations with a device, use a pinctrl-N property for some
number N, like this example you could place in your board's DTS file:
#include "board-pinctrl.dtsi"
&uart3 {
pinctrl-0 = <&uart3_default>;
pinctrl-1 = <&uart3_sleep>;
pinctrl-names = "default", "sleep";
};
compatible: "arm,mps2-pinctrl"
include: base.yaml
child-binding:
description: |
Definitions for a pinctrl state.
child-binding:
include:
- name: pincfg-node.yaml
property-allowlist:
- input-enable
properties:
pinmux:
required: true
type: array
description: |
An array of pins sharing the same group properties. Each
element of the array is an integer constructed from the
pin number and the alternative function of the pin.

View file

@ -52,6 +52,8 @@ struct gpio_cmsdk_ahb {
volatile uint32_t ub_masked[256];
};
int cmsdk_ahb_gpio_config(const struct device *dev, uint32_t mask, gpio_flags_t flags);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,124 @@
/*
* Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#define MPS2_ALT_FUNC_POS 0
#define MPS2_ALT_FUNC_MASK 0x3
#define MPS2_EXP_NUM_POS 2
#define MPS2_EXP_NUM_MASK 0x3F
#define MPS2_PINCTRL_FUNC_UART 0
#define MPS2_PINCTRL_FUNC_GPIO 1
#define MPS2_PINCTRL_FUNC_I2C 2
#define MPS2_PINCTRL_FUNC_SPI 3
#define MPS2_PINMUX(alt_func, exp_num) (exp_num << MPS2_EXP_NUM_POS | \
alt_func << MPS2_ALT_FUNC_POS)
/*
* This is the mapping from the ARM MPS2 Board pins to GPIO
* controllers.
*
* D0 : EXT_0
* D1 : EXT_4
* D2 : EXT_2
* D3 : EXT_3
* D4 : EXT_1
* D5 : EXT_6
* D6 : EXT_7
* D7 : EXT_8
* D8 : EXT_9
* D9 : EXT_10
* D10 : EXT_12
* D11 : EXT_13
* D12 : EXT_14
* D13 : EXT_11
* D14 : EXT_15
* D15 : EXT_5
* D16 : EXT_16
* D17 : EXT_17
* D18 : EXT_18
* D19 : EXT_19
* D20 : EXT_20
* D21 : EXT_21
* D22 : EXT_22
* D23 : EXT_23
* D24 : EXT_24
* D25 : EXT_25
* D26 : EXT_26
* D27 : EXT_30
* D28 : EXT_28
* D29 : EXT_29
* D30 : EXT_27
* D31 : EXT_32
* D32 : EXT_33
* D33 : EXT_34
* D34 : EXT_35
* D35 : EXT_36
* D36 : EXT_38
* D37 : EXT_39
* D38 : EXT_40
* D39 : EXT_44
* D40 : EXT_41
* D41 : EXT_31
* D42 : EXT_37
* D43 : EXT_42
* D44 : EXT_43
* D45 : EXT_45
* D46 : EXT_46
* D47 : EXT_47
* D48 : EXT_48
* D49 : EXT_49
* D50 : EXT_50
* D51 : EXT_51
*
* UART_3_RX : D0
* UART_3_TX : D1
* SPI_3_CS : D10
* SPI_3_MOSI : D11
* SPI_3_MISO : D12
* SPI_3_SCLK : D13
* I2C_3_SDA : D14
* I2C_3_SCL : D15
* UART_4_RX : D26
* UART_4_TX : D30
* SPI_4_CS : D36
* SPI_4_MOSI : D37
* SPI_4_MISO : D38
* SPI_4_SCK : D39
* I2C_4_SDA : D40
* I2C_4_SCL : D41
*
*/
/* GPIO 0 */
#define UART3_RXD_EXP MPS2_PINMUX(MPS2_PINCTRL_FUNC_UART, 0)
#define UART3_TXD_EXP MPS2_PINMUX(MPS2_PINCTRL_FUNC_UART, 4)
#define SBCON2_SCL_EXP MPS2_PINMUX(MPS2_PINCTRL_FUNC_I2C, 5)
#define SBCON2_SDA_EXP MPS2_PINMUX(MPS2_PINCTRL_FUNC_I2C, 15)
#define SPI3_SCK_EXP MPS2_PINMUX(MPS2_PINCTRL_FUNC_SPI, 11)
#define SPI3_SS_EXP MPS2_PINMUX(MPS2_PINCTRL_FUNC_SPI, 12)
#define SPI3_MOSI_EXP MPS2_PINMUX(MPS2_PINCTRL_FUNC_SPI, 13)
#define SPI3_MISO_EXP MPS2_PINMUX(MPS2_PINCTRL_FUNC_SPI, 14)
/* GPIO 1 */
#define SPI2_SS_EXP MPS2_PINMUX(MPS2_PINCTRL_FUNC_SPI, 16)
#define SPI2_MISO_EXP MPS2_PINMUX(MPS2_PINCTRL_FUNC_SPI, 17)
#define SPI2_MOSI_EXP MPS2_PINMUX(MPS2_PINCTRL_FUNC_SPI, 18)
#define SPI2_SCK_EXP MPS2_PINMUX(MPS2_PINCTRL_FUNC_SPI, 19)
#define UART4_RXD_EXP MPS2_PINMUX(MPS2_PINCTRL_FUNC_UART, 26)
#define UART4_TXD_EXP MPS2_PINMUX(MPS2_PINCTRL_FUNC_UART, 30)
#define SBCON3_SCL_EXP MPS2_PINMUX(MPS2_PINCTRL_FUNC_I2C, 31)
/* GPIO 2 */
#define SBCON3_SDA_EXP MPS2_PINMUX(MPS2_PINCTRL_FUNC_I2C, 41)
#define SPI4_SS_EXP MPS2_PINMUX(MPS2_PINCTRL_FUNC_SPI, 38)
#define SPI4_MOSI_EXP MPS2_PINMUX(MPS2_PINCTRL_FUNC_SPI, 39)
#define SPI4_MISO_EXP MPS2_PINMUX(MPS2_PINCTRL_FUNC_SPI, 40)
#define SPI4_SCK_EXP MPS2_PINMUX(MPS2_PINCTRL_FUNC_SPI, 44)

View file

@ -0,0 +1,51 @@
/*
* Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/dt-bindings/pinctrl/arm-mps2-pinctrl.h>
/**
* @brief Type to hold a pin's pinctrl configuration.
*/
struct mps2_pinctrl_soc_pin {
/** Pin number 0..52 */
uint32_t pin_num : 6;
/** Alternative function (UART, SPI, etc.) */
uint32_t alt_func : 2;
/** Enable the pin as an input */
uint32_t input_enable : 1;
};
typedef struct mps2_pinctrl_soc_pin pinctrl_soc_pin_t;
/**
* @brief Utility macro to initialize each pin.
*
* @param node_id Node identifier.
* @param prop Property name.
* @param idx Property entry index.
*/
#define Z_PINCTRL_STATE_PIN_INIT(node_id, prop, idx) \
{ \
MPS2_GET_PIN_NUM(DT_PROP_BY_IDX(node_id, prop, idx)), \
MPS2_GET_PIN_ALT_FUNC(DT_PROP_BY_IDX(node_id, prop, idx)), \
DT_PROP(node_id, input_enable), \
},
/**
* @brief Utility macro to initialize state pins contained in a given property.
*
* @param node_id Node identifier.
* @param prop Property name describing state pins.
*/
#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \
{DT_FOREACH_CHILD_VARGS(DT_PHANDLE(node_id, prop), \
DT_FOREACH_PROP_ELEM, pinmux, \
Z_PINCTRL_STATE_PIN_INIT)}
#define MPS2_GET_PIN_NUM(pinctrl) \
(((pinctrl) >> MPS2_EXP_NUM_POS) & MPS2_EXP_NUM_MASK)
#define MPS2_GET_PIN_ALT_FUNC(pinctrl) \
(((pinctrl) >> MPS2_ALT_FUNC_POS) & MPS2_ALT_FUNC_MASK)