drivers: add ch32v00x pinctrl support

This commit adds the pinctrl driver for WCH CH32V003.

Signed-off-by: Michael Hope <michaelh@juju.nz>
Signed-off-by: Dhiru Kholia <dhiru.kholia@gmail.com>
This commit is contained in:
Michael Hope 2024-06-01 21:49:19 +05:30 committed by Fabio Baltieri
commit 6d3348bd83
7 changed files with 316 additions and 0 deletions

View file

@ -40,5 +40,6 @@ 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)
zephyr_library_sources_ifdef(CONFIG_PINCTRL_WCH_AFIO pinctrl_wch_afio.c)
add_subdirectory(renesas)

View file

@ -67,6 +67,7 @@ source "drivers/pinctrl/Kconfig.ene"
source "drivers/pinctrl/Kconfig.zynqmp"
source "drivers/pinctrl/Kconfig.max32"
source "drivers/pinctrl/Kconfig.mec5"
source "drivers/pinctrl/Kconfig.wch_afio"
rsource "renesas/Kconfig"

View file

@ -0,0 +1,9 @@
# Copyright (c) 2024 Michael Hope
# SPDX-License-Identifier: Apache-2.0
config PINCTRL_WCH_AFIO
bool "WCH AFIO pin controller driver"
default y
depends on DT_HAS_WCH_AFIO_ENABLED
help
WCH AFIO pin controller driver.

View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 2024 Michael Hope
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/drivers/pinctrl.h>
#include <zephyr/dt-bindings/pinctrl/ch32v003-pinctrl.h>
#include <ch32fun.h>
static GPIO_TypeDef *const wch_afio_pinctrl_regs[] = {
(GPIO_TypeDef *)DT_REG_ADDR(DT_NODELABEL(gpioa)),
(GPIO_TypeDef *)DT_REG_ADDR(DT_NODELABEL(gpioc)),
(GPIO_TypeDef *)DT_REG_ADDR(DT_NODELABEL(gpiod)),
};
int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg)
{
int i;
for (i = 0; i < pin_cnt; i++, pins++) {
uint8_t port = (pins->config >> CH32V003_PINCTRL_PORT_SHIFT) & 0x03;
uint8_t pin = (pins->config >> CH32V003_PINCTRL_PIN_SHIFT) & 0x0F;
uint8_t bit0 = (pins->config >> CH32V003_PINCTRL_RM_BASE_SHIFT) & 0x1F;
uint8_t remap = (pins->config >> CH32V003_PINCTRL_RM_SHIFT) & 0x3;
GPIO_TypeDef *regs = wch_afio_pinctrl_regs[port];
uint32_t pcfr1 = AFIO->PCFR1;
uint8_t cfg = 0;
if (pins->output_high || pins->output_low) {
cfg |= (pins->slew_rate + 1);
if (pins->drive_open_drain) {
cfg |= BIT(2);
}
/* Select the alternate function */
cfg |= BIT(3);
} else {
if (pins->bias_pull_up || pins->bias_pull_down) {
cfg |= BIT(3);
}
}
regs->CFGLR = (regs->CFGLR & ~(0x0F << (pin * 4))) | (cfg << (pin * 4));
if (pins->output_high) {
regs->OUTDR |= BIT(pin);
regs->BSHR |= BIT(pin);
} else if (pins->output_low) {
regs->OUTDR |= BIT(pin);
/* Reset the pin. */
regs->BSHR |= BIT(pin + 16);
} else {
regs->OUTDR &= ~(1 << pin);
if (pins->bias_pull_up) {
regs->BSHR = BIT(pin);
}
if (pins->bias_pull_down) {
regs->BCR = BIT(pin);
}
}
if (bit0 == CH32V003_PINMUX_I2C1_RM) {
pcfr1 |= ((remap & 1) << CH32V003_PINMUX_I2C1_RM) |
(((remap >> 1) & 1) << CH32V003_PINMUX_I2C1_RM1);
} else if (bit0 == CH32V003_PINMUX_USART1_RM) {
pcfr1 |= ((remap & 1) << CH32V003_PINMUX_USART1_RM) |
(((remap >> 1) & 1) << CH32V003_PINMUX_USART1_RM1);
} else {
pcfr1 |= remap << bit0;
}
AFIO->PCFR1 = pcfr1;
}
return 0;
}

View file

@ -0,0 +1,52 @@
# Copyright (c) 2024 Michael Hope
# SPDX-License-Identifier: Apache-2.0
description: WCH CH32V00x AFIO
compatible: "wch,afio"
include: base.yaml
properties:
reg:
required: true
"#address-cells":
required: true
const: 1
"#size-cells":
required: true
const: 1
child-binding:
description: |
Each child node defines the configuration for a particular state.
child-binding:
description: |
The grandchild nodes group pins that share the same pin configuration.
include:
- name: pincfg-node.yaml
property-allowlist:
- bias-high-impedance
- bias-pull-up
- bias-pull-down
- drive-open-drain
- drive-push-pull
- output-high
- output-low
properties:
slew-rate:
type: string
default: "max-speed-2mhz"
enum:
- "max-speed-10mhz"
- "max-speed-2mhz"
- "max-speed-30mhz"
pinmux:
required: true
type: array
description: |
An array of pins sharing the same group properties. The pins should
be defined using pre-defined macros.

View file

@ -0,0 +1,136 @@
/*
* Copyright (c) 2024 Michael Hope
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __CH32V003_PINCTRL_H__
#define __CH32V003_PINCTRL_H__
#define CH32V003_PINMUX_PORT_PA 0
#define CH32V003_PINMUX_PORT_PC 1
#define CH32V003_PINMUX_PORT_PD 2
/*
* Defines the starting bit for the remap field. Note that the I2C1 and USART1 fields are not
* contigious.
*/
#define CH32V003_PINMUX_SPI1_RM 0
#define CH32V003_PINMUX_I2C1_RM 1
#define CH32V003_PINMUX_I2C1_RM1 23
#define CH32V003_PINMUX_USART1_RM 2
#define CH32V003_PINMUX_USART1_RM1 21
#define CH32V003_PINMUX_TIM1_RM 6
#define CH32V003_PINMUX_TIM2_RM 8
/* Port number with 0-2 */
#define CH32V003_PINCTRL_PORT_SHIFT 0
/* Pin number 0-15 */
#define CH32V003_PINCTRL_PIN_SHIFT 2
/* Base remap bit 0-31 */
#define CH32V003_PINCTRL_RM_BASE_SHIFT 6
/* Function remapping ID 0-3 */
#define CH32V003_PINCTRL_RM_SHIFT 11
#define CH32V003_PINMUX_DEFINE(port, pin, rm, remapping) \
((CH32V003_PINMUX_PORT_##port << CH32V003_PINCTRL_PORT_SHIFT) | \
(pin << CH32V003_PINCTRL_PIN_SHIFT) | \
(CH32V003_PINMUX_##rm##_RM << CH32V003_PINCTRL_RM_BASE_SHIFT) | \
(remapping << CH32V003_PINCTRL_RM_SHIFT))
#define TIM1_ETR_PC5_0 CH32V003_PINMUX_DEFINE(PC, 5, TIM1, 0)
#define TIM1_ETR_PC5_1 CH32V003_PINMUX_DEFINE(PC, 5, TIM1, 1)
#define TIM1_ETR_PD4_2 CH32V003_PINMUX_DEFINE(PD, 4, TIM1, 2)
#define TIM1_ETR_PC2_3 CH32V003_PINMUX_DEFINE(PC, 2, TIM1, 3)
#define TIM1_CH1_PD2_0 CH32V003_PINMUX_DEFINE(PD, 2, TIM1, 0)
#define TIM1_CH1_PC6_1 CH32V003_PINMUX_DEFINE(PC, 6, TIM1, 1)
#define TIM1_CH1_PD2_2 CH32V003_PINMUX_DEFINE(PD, 2, TIM1, 2)
#define TIM1_CH1_PC4_3 CH32V003_PINMUX_DEFINE(PC, 4, TIM1, 3)
#define TIM1_CH2_PA1_0 CH32V003_PINMUX_DEFINE(PA, 1, TIM1, 0)
#define TIM1_CH2_PC7_1 CH32V003_PINMUX_DEFINE(PC, 7, TIM1, 1)
#define TIM1_CH2_PA1_2 CH32V003_PINMUX_DEFINE(PA, 1, TIM1, 2)
#define TIM1_CH2_PC7_3 CH32V003_PINMUX_DEFINE(PC, 7, TIM1, 3)
#define TIM1_CH3_PC3_0 CH32V003_PINMUX_DEFINE(PC, 3, TIM1, 0)
#define TIM1_CH3_PC0_1 CH32V003_PINMUX_DEFINE(PC, 0, TIM1, 1)
#define TIM1_CH3_PC3_2 CH32V003_PINMUX_DEFINE(PC, 3, TIM1, 2)
#define TIM1_CH3_PC5_3 CH32V003_PINMUX_DEFINE(PC, 5, TIM1, 3)
#define TIM1_CH4_PC4_0 CH32V003_PINMUX_DEFINE(PC, 4, TIM1, 0)
#define TIM1_CH4_PD3_1 CH32V003_PINMUX_DEFINE(PD, 3, TIM1, 1)
#define TIM1_CH4_PC4_2 CH32V003_PINMUX_DEFINE(PC, 4, TIM1, 2)
#define TIM1_CH4_PD4_3 CH32V003_PINMUX_DEFINE(PD, 4, TIM1, 3)
#define TIM1_BKIN_PC2_0 CH32V003_PINMUX_DEFINE(PC, 2, TIM1, 0)
#define TIM1_BKIN_PC1_1 CH32V003_PINMUX_DEFINE(PC, 1, TIM1, 1)
#define TIM1_BKIN_PC2_2 CH32V003_PINMUX_DEFINE(PC, 2, TIM1, 2)
#define TIM1_BKIN_PC1_3 CH32V003_PINMUX_DEFINE(PC, 1, TIM1, 3)
#define TIM1_CH1N_PD0_0 CH32V003_PINMUX_DEFINE(PD, 0, TIM1, 0)
#define TIM1_CH1N_PC3_1 CH32V003_PINMUX_DEFINE(PC, 3, TIM1, 1)
#define TIM1_CH1N_PD0_2 CH32V003_PINMUX_DEFINE(PD, 0, TIM1, 2)
#define TIM1_CH1N_PC3_3 CH32V003_PINMUX_DEFINE(PC, 3, TIM1, 3)
#define TIM1_CH2N_PA2_0 CH32V003_PINMUX_DEFINE(PA, 2, TIM1, 0)
#define TIM1_CH2N_PC4_1 CH32V003_PINMUX_DEFINE(PC, 4, TIM1, 1)
#define TIM1_CH2N_PA2_2 CH32V003_PINMUX_DEFINE(PA, 2, TIM1, 2)
#define TIM1_CH2N_PD2_3 CH32V003_PINMUX_DEFINE(PD, 2, TIM1, 3)
#define TIM1_CH3N_PD1_0 CH32V003_PINMUX_DEFINE(PD, 1, TIM1, 0)
#define TIM1_CH3N_PD1_1 CH32V003_PINMUX_DEFINE(PD, 1, TIM1, 1)
#define TIM1_CH3N_PD1_2 CH32V003_PINMUX_DEFINE(PD, 1, TIM1, 2)
#define TIM1_CH3N_PC6_3 CH32V003_PINMUX_DEFINE(PC, 6, TIM1, 3)
#define TIM2_ETR_PD4_0 CH32V003_PINMUX_DEFINE(PD, 4, TIM2, 0)
#define TIM2_ETR_PC5_1 CH32V003_PINMUX_DEFINE(PC, 5, TIM2, 1)
#define TIM2_ETR_PC1_2 CH32V003_PINMUX_DEFINE(PC, 1, TIM2, 2)
#define TIM2_ETR_PC1_3 CH32V003_PINMUX_DEFINE(PC, 1, TIM2, 3)
#define TIM2_CH1_PD4_0 CH32V003_PINMUX_DEFINE(PD, 4, TIM2, 0)
#define TIM2_CH1_PC5_1 CH32V003_PINMUX_DEFINE(PC, 5, TIM2, 1)
#define TIM2_CH1_PC1_2 CH32V003_PINMUX_DEFINE(PC, 1, TIM2, 2)
#define TIM2_CH1_PC1_3 CH32V003_PINMUX_DEFINE(PC, 1, TIM2, 3)
#define TIM2_CH2_PD3_0 CH32V003_PINMUX_DEFINE(PD, 3, TIM2, 0)
#define TIM2_CH2_PC2_1 CH32V003_PINMUX_DEFINE(PC, 2, TIM2, 1)
#define TIM2_CH2_PD3_2 CH32V003_PINMUX_DEFINE(PD, 3, TIM2, 2)
#define TIM2_CH2_PC7_3 CH32V003_PINMUX_DEFINE(PC, 7, TIM2, 3)
#define TIM2_CH3_PC0_0 CH32V003_PINMUX_DEFINE(PC, 0, TIM2, 0)
#define TIM2_CH3_PD2_1 CH32V003_PINMUX_DEFINE(PD, 2, TIM2, 1)
#define TIM2_CH3_PC0_2 CH32V003_PINMUX_DEFINE(PC, 0, TIM2, 2)
#define TIM2_CH3_PD6_3 CH32V003_PINMUX_DEFINE(PD, 6, TIM2, 3)
#define TIM2_CH4_PD7_0 CH32V003_PINMUX_DEFINE(PD, 7, TIM2, 0)
#define TIM2_CH4_PC1_1 CH32V003_PINMUX_DEFINE(PC, 1, TIM2, 1)
#define TIM2_CH4_PD7_2 CH32V003_PINMUX_DEFINE(PD, 7, TIM2, 2)
#define TIM2_CH4_PD5_3 CH32V003_PINMUX_DEFINE(PD, 5, TIM2, 3)
#define USART1_CK_PD4_0 CH32V003_PINMUX_DEFINE(PD, 4, USART1, 0)
#define USART1_CK_PD7_1 CH32V003_PINMUX_DEFINE(PD, 7, USART1, 1)
#define USART1_CK_PD7_2 CH32V003_PINMUX_DEFINE(PD, 7, USART1, 2)
#define USART1_CK_PC5_3 CH32V003_PINMUX_DEFINE(PC, 5, USART1, 3)
#define USART1_TX_PD5_0 CH32V003_PINMUX_DEFINE(PD, 5, USART1, 0)
#define USART1_TX_PD0_1 CH32V003_PINMUX_DEFINE(PD, 0, USART1, 1)
#define USART1_TX_PD6_2 CH32V003_PINMUX_DEFINE(PD, 6, USART1, 2)
#define USART1_TX_PC0_3 CH32V003_PINMUX_DEFINE(PC, 0, USART1, 3)
#define USART1_RX_PD6_0 CH32V003_PINMUX_DEFINE(PD, 6, USART1, 0)
#define USART1_RX_PD1_1 CH32V003_PINMUX_DEFINE(PD, 1, USART1, 1)
#define USART1_RX_PD5_2 CH32V003_PINMUX_DEFINE(PD, 5, USART1, 2)
#define USART1_RX_PC1_3 CH32V003_PINMUX_DEFINE(PC, 1, USART1, 3)
#define USART1_CTS_PD3_0 CH32V003_PINMUX_DEFINE(PD, 3, USART1, 0)
#define USART1_CTS_PC3_1 CH32V003_PINMUX_DEFINE(PC, 3, USART1, 1)
#define USART1_CTS_PC6_2 CH32V003_PINMUX_DEFINE(PC, 6, USART1, 2)
#define USART1_CTS_PC6_3 CH32V003_PINMUX_DEFINE(PC, 6, USART1, 3)
#define USART1_RTS_PC2_0 CH32V003_PINMUX_DEFINE(PC, 2, USART1, 0)
#define USART1_RTS_PC2_1 CH32V003_PINMUX_DEFINE(PC, 2, USART1, 1)
#define USART1_RTS_PC7_2 CH32V003_PINMUX_DEFINE(PC, 7, USART1, 2)
#define USART1_RTS_PC7_3 CH32V003_PINMUX_DEFINE(PC, 7, USART1, 3)
#define SPI1_NSS_PC1_0 CH32V003_PINMUX_DEFINE(PC, 1, SPI1, 0)
#define SPI1_NSS_PC0_1 CH32V003_PINMUX_DEFINE(PC, 0, SPI1, 1)
#define SPI1_SCK_PC5_0 CH32V003_PINMUX_DEFINE(PC, 5, SPI1, 0)
#define SPI1_SCK_PC5_1 CH32V003_PINMUX_DEFINE(PC, 5, SPI1, 1)
#define SPI1_MISO_PC7_0 CH32V003_PINMUX_DEFINE(PC, 7, SPI1, 0)
#define SPI1_MISO_PC7_1 CH32V003_PINMUX_DEFINE(PC, 7, SPI1, 1)
#define SPI1_MOSI_PC6_0 CH32V003_PINMUX_DEFINE(PC, 6, SPI1, 0)
#define SPI1_MOSI_PC6_1 CH32V003_PINMUX_DEFINE(PC, 6, SPI1, 1)
#define I2C1_SCL_PC2_0 CH32V003_PINMUX_DEFINE(PC, 2, I2C1, 0)
#define I2C1_SCL_PD1_1 CH32V003_PINMUX_DEFINE(PD, 1, I2C1, 1)
#define I2C1_SCL_PC5_2 CH32V003_PINMUX_DEFINE(PC, 5, I2C1, 2)
#define I2C1_SDA_PC1_0 CH32V003_PINMUX_DEFINE(PC, 1, I2C1, 0)
#define I2C1_SDA_PD0_1 CH32V003_PINMUX_DEFINE(PD, 0, I2C1, 1)
#define I2C1_SDA_PC6_2 CH32V003_PINMUX_DEFINE(PC, 6, I2C1, 2)
#endif /* __CH32V003_PINCTRL_H__ */

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2024 Michael Hope
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __PINCTRL_SOC_H__
#define __PINCTRL_SOC_H__
/**
* @brief Type to hold a pin's pinctrl configuration.
*/
struct ch32v003_pinctrl_soc_pin {
uint32_t config: 22;
bool bias_pull_up: 1;
bool bias_pull_down: 1;
bool drive_open_drain: 1;
bool drive_push_pull: 1;
bool output_high: 1;
bool output_low: 1;
uint8_t slew_rate: 2;
};
typedef struct ch32v003_pinctrl_soc_pin pinctrl_soc_pin_t;
#define Z_PINCTRL_STATE_PIN_INIT(node_id, prop, idx) \
{ \
.config = DT_PROP_BY_IDX(node_id, prop, idx), \
.bias_pull_up = DT_PROP(node_id, bias_pull_up), \
.bias_pull_down = DT_PROP(node_id, bias_pull_down), \
.drive_open_drain = DT_PROP(node_id, drive_open_drain), \
.drive_push_pull = DT_PROP(node_id, drive_push_pull), \
.output_high = DT_PROP(node_id, output_high), \
.output_low = DT_PROP(node_id, output_low), \
.slew_rate = DT_ENUM_IDX(node_id, slew_rate), \
},
#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)}
#endif