drivers: pinctrl: Added pinctrl driver for RPi Pico

Added a pinctrl driver for the Raspberry Pi Pico series

Signed-off-by: Yonatan Schachter <yonatan.schachter@gmail.com>
This commit is contained in:
Yonatan Schachter 2021-11-30 00:29:09 +02:00 committed by Carles Cufí
parent db5b2780bf
commit fd59038312
10 changed files with 315 additions and 0 deletions

View file

@ -491,6 +491,7 @@
/dts/bindings/*/nordic* @anangl
/dts/bindings/*/nxp* @mmahadevan108 @dleach02
/dts/bindings/*/openisa* @dleach02
/dts/bindings/*/raspberrypi*pico* @yonsch
/dts/bindings/*/st* @erwango
/dts/bindings/sensor/ams* @alexanderwachter
/dts/bindings/*/sifive* @mateusz-holenko @kgugala @pgielda

View file

@ -7,4 +7,5 @@ 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_NRF pinctrl_nrf.c)
zephyr_library_sources_ifdef(CONFIG_PINCTRL_RCAR_PFC pfc_rcar.c)
zephyr_library_sources_ifdef(CONFIG_PINCTRL_RPI_PICO pinctrl_rpi_pico.c)
zephyr_library_sources_ifdef(CONFIG_PINCTRL_STM32 pinctrl_stm32.c)

View file

@ -32,6 +32,7 @@ config PINCTRL_DYNAMIC
source "drivers/pinctrl/Kconfig.gd32"
source "drivers/pinctrl/Kconfig.nrf"
source "drivers/pinctrl/Kconfig.rcar"
source "drivers/pinctrl/Kconfig.rpi_pico"
source "drivers/pinctrl/Kconfig.stm32"
endif # PINCTRL

View file

@ -0,0 +1,12 @@
# Copyright (c) 2021 Yonatan Schachter
# SPDX-License-Identifier: Apache-2.0
DT_COMPAT_RPI_PICO_PINCTRL := raspberrypi,pico-pinctrl
config PINCTRL_RPI_PICO
bool "RaspberryPi Pico pin controller driver"
depends on SOC_FAMILY_RPI_PICO
default $(dt_compat_enabled,$(DT_COMPAT_RPI_PICO_PINCTRL))
select PICOSDK_USE_GPIO
help
RaspberryPi Pico pinctrl driver

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2021 Yonatan Schachter
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <drivers/pinctrl.h>
/* pico-sdk includes */
#include <hardware/gpio.h>
static void pinctrl_configure_pin(const pinctrl_soc_pin_t *pin)
{
gpio_init(pin->pin_num);
gpio_set_function(pin->pin_num, pin->alt_func);
gpio_set_pulls(pin->pin_num, pin->pullup, pin->pulldown);
gpio_set_drive_strength(pin->pin_num, pin->drive_strength);
gpio_set_slew_rate(pin->pin_num, (pin->slew_rate ?
GPIO_SLEW_RATE_FAST : GPIO_SLEW_RATE_SLOW));
gpio_set_input_hysteresis_enabled(pin->pin_num, pin->schmitt_enable);
gpio_set_input_enabled(pin->pin_num, pin->input_enable);
}
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++) {
pinctrl_configure_pin(pins++);
}
return 0;
}

View file

@ -43,6 +43,13 @@
clock-frequency = <125000000>;
#clock-cells = <0>;
};
pinctrl: pin-controller@40014000 {
compatible = "raspberrypi,pico-pinctrl";
reg = <0x40014000 DT_SIZE_K(4)>;
status = "okay";
label = "PINCTRL";
};
};
};

View file

@ -0,0 +1,123 @@
# Copyright (c) 2021 Teslabs Engineering S.L.
# Copyright (c) 2021 Yonatan Schachter
# SPDX-License-Identifier: Apache-2.0
description: |
The RPi Pico pin controller is a node responsible for controlling
pin function selection and pin properties, such as routing a UART0 Rx
to pin 1 and enabling the pullup resistor on that pin.
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:
/* You can put this in places like a board-pinctrl.dtsi file in
* your board directory, or a devicetree overlay in your application.
*/
/* include pre-defined combinations for the SoC variant used by the board */
#include <dt-bindings/pinctrl/rpi-pico-rp2040-pinctrl.h>
&pinctrl {
/* configuration for the usart0 "default" state */
uart0_default: uart0_default {
/* group 1 */
group1 {
/* configure P0 as UART0 TX */
pinmux = <UART0_TX_P0>;
};
/* group 2 */
group2 {
/* configure P1 as UART0 RX */
pinmux = <UART0_RX_P1>;
/* enable input on pin 1 */
input-enable;
};
};
};
The 'uart0_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.
A group can also specify shared pin properties common to all the specified
pins, such as the 'input-enable' property in group 2. Here is a list of
supported standard pin properties:
- bias-disable: Disable pull-up/down (default, not required).
- bias-pull-up: Enable pull-up resistor.
- bias-pull-down: Enable pull-down resistor.
- input-enable: Enable input from the pin.
- input-schmitt-enable: Enable input hysteresys.
- drive-strength: Set the drive strength of the pin, in milliamps. Possible
values are: 2, 4, 8, 12 (default: 4mA)
- slew-rate: If set to 0, slew rate is set to slow. If set to 1, it is set
to fast.
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"
&uart0 {
pinctrl-0 = <&uart0_default>;
pinctrl-1 = <&uart0_sleep>;
pinctrl-names = "default", "sleep";
};
compatible: "raspberrypi,pico-pinctrl"
include:
- name: base.yaml
- name: pincfg-node-group.yaml
child-binding:
child-binding:
property-allowlist:
- bias-disable
- bias-pull-down
- bias-pull-up
- input-enable
- input-schmitt-enable
- drive-strength
- slew-rate
child-binding:
description: |
Definitions for a pinctrl state.
child-binding:
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.
drive-strength:
enum:
- 2
- 4
- 8
- 12
default: 4
description: |
The drive strength of a pin, in mA. The default value is 4mA, as this
is the power on reset value.
slew-rate:
enum:
- 0
- 1
default: 0
description: |
The slew rate of a pin. 0 corresponds to slow, and 1 corresponds to fast.
The default value is 0 (slow), as this is the power on reset value.

View file

@ -0,0 +1,62 @@
/*
* Copyright (c) 2021, Yonatan Schachter
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __RP2040_PINCTRL_H__
#define __RP2040_PINCTRL_H__
#define RP2_PINCTRL_GPIO_FUNC_XIP 0
#define RP2_PINCTRL_GPIO_FUNC_SPI 1
#define RP2_PINCTRL_GPIO_FUNC_UART 2
#define RP2_PINCTRL_GPIO_FUNC_I2C 3
#define RP2_PINCTRL_GPIO_FUNC_PWM 4
#define RP2_PINCTRL_GPIO_FUNC_SIO 5
#define RP2_PINCTRL_GPIO_FUNC_PIO0 6
#define RP2_PINCTRL_GPIO_FUNC_PIO1 7
#define RP2_PINCTRL_GPIO_FUNC_GPCK 8
#define RP2_PINCTRL_GPIO_FUNC_USB 9
#define RP2_PINCTRL_GPIO_FUNC_NULL 0xf
#define RP2_ALT_FUNC_POS 0
#define RP2_ALT_FUNC_MASK 0xf
#define RP2_PIN_NUM_POS 4
#define RP2_PIN_NUM_MASK 0x1f
#define RP2040_PINMUX(pin_num, alt_func) (pin_num << RP2_PIN_NUM_POS | \
alt_func << RP2_ALT_FUNC_POS)
#define UART0_TX_P0 RP2040_PINMUX(0, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART0_RX_P1 RP2040_PINMUX(1, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART0_CTS_P2 RP2040_PINMUX(2, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART0_RTS_P3 RP2040_PINMUX(3, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART1_TX_P4 RP2040_PINMUX(4, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART1_RX_P5 RP2040_PINMUX(5, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART1_CTS_P6 RP2040_PINMUX(6, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART1_RTS_P7 RP2040_PINMUX(7, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART1_TX_P8 RP2040_PINMUX(8, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART1_RX_P9 RP2040_PINMUX(9, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART1_CTS_P10 RP2040_PINMUX(10, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART1_RTS_P11 RP2040_PINMUX(11, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART0_TX_P12 RP2040_PINMUX(12, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART0_RX_P13 RP2040_PINMUX(13, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART0_CTS_P14 RP2040_PINMUX(14, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART0_RTS_P15 RP2040_PINMUX(15, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART0_TX_P16 RP2040_PINMUX(16, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART0_RX_P17 RP2040_PINMUX(17, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART0_CTS_P18 RP2040_PINMUX(18, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART0_RTS_P19 RP2040_PINMUX(19, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART1_TX_P20 RP2040_PINMUX(20, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART1_RX_P21 RP2040_PINMUX(21, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART1_CTS_P22 RP2040_PINMUX(22, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART1_RTS_P23 RP2040_PINMUX(23, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART1_TX_P24 RP2040_PINMUX(24, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART1_RX_P25 RP2040_PINMUX(25, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART1_CTS_P26 RP2040_PINMUX(26, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART1_RTS_P27 RP2040_PINMUX(27, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART0_TX_P28 RP2040_PINMUX(28, RP2_PINCTRL_GPIO_FUNC_UART)
#define UART0_RX_P29 RP2040_PINMUX(29, RP2_PINCTRL_GPIO_FUNC_UART)
#endif /* __RP2040_PINCTRL_H__ */

View file

@ -7,4 +7,7 @@ if SOC_FAMILY_RPI_PICO
source "soc/arm/rpi_pico/*/Kconfig.defconfig.series"
config PINCTRL
default y
endif # SOC_FAMILY_RPI_PICO

View file

@ -0,0 +1,71 @@
/*
* Copyright (c) 2021 Yonatan Schachter
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_SOC_ARM_RPI_PICO_RP2_PINCTRL_SOC_H_
#define ZEPHYR_SOC_ARM_RPI_PICO_RP2_PINCTRL_SOC_H_
#include <dt-bindings/pinctrl/rpi-pico-rp2040-pinctrl.h>
/**
* @brief Type to hold a pin's pinctrl configuration.
*/
struct rpi_pinctrl_soc_pin {
/** Pin number 0..29 */
uint32_t pin_num : 5;
/** Alternative function (UART, SPI, etc.) */
uint32_t alt_func : 4;
/** Maximum current used by a pin, in mA */
uint32_t drive_strength : 4;
/** Slew rate, may be either false (slow) or true (fast) */
uint32_t slew_rate : 1;
/** Enable the internal pull up resistor */
uint32_t pullup : 1;
/** Enable the internal pull down resistor */
uint32_t pulldown : 1;
/** Enable the pin as an input */
uint32_t input_enable : 1;
/** Enable the internal schmitt trigger */
uint32_t schmitt_enable : 1;
};
typedef struct rpi_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) \
{ \
RP2_GET_PIN_NUM(DT_PROP_BY_IDX(node_id, prop, idx)), \
RP2_GET_PIN_ALT_FUNC(DT_PROP_BY_IDX(node_id, prop, idx)), \
DT_ENUM_IDX(node_id, drive_strength), \
DT_ENUM_IDX(node_id, slew_rate), \
DT_PROP(node_id, bias_pull_up), \
DT_PROP(node_id, bias_pull_down), \
DT_PROP(node_id, input_enable), \
DT_PROP(node_id, input_schmitt_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 RP2_GET_PIN_NUM(pinctrl) \
(((pinctrl) >> RP2_PIN_NUM_POS) & RP2_PIN_NUM_MASK)
#define RP2_GET_PIN_ALT_FUNC(pinctrl) \
(((pinctrl) >> RP2_ALT_FUNC_POS) & RP2_ALT_FUNC_MASK)
#endif /* ZEPHYR_SOC_ARM_RPI_PICO_RP2_PINCTRL_SOC_H_ */