Skip to content

Commit

Permalink
drivers: pinctrl: add pin group for NuMaker pinctrl
Browse files Browse the repository at this point in the history
Update Nuvoton numaker series pinctrl, let support pin group.

Signed-off-by: cyliang tw <[email protected]>
  • Loading branch information
SeppoTakalo authored and cyliangtw committed Jun 27, 2023
1 parent a7498c3 commit 4894d9d
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 62 deletions.
18 changes: 11 additions & 7 deletions boards/arm/numaker_pfm_m467/numaker_pfm_m467-pinctrl.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,20 @@

&pinctrl {
uart0_default: uart0_default {
pinmux = <PB12MFP_UART0_RXD>,
<PB13MFP_UART0_TXD>;
group0 {
pinmux = <PB12MFP_UART0_RXD>,
<PB13MFP_UART0_TXD>;
};
};

/* TX/RX/RTS/CTS/RST --> D1/D0/A2/A3/D2 --> PB3/PB2/PB8/PB9/PC9 */
uart1_default: uart1_default {
pinmux = <PB9MFP_UART1_nCTS>,
<PB8MFP_UART1_nRTS>,
<PB2MFP_UART1_RXD>,
<PB3MFP_UART1_TXD>,
<PC9MFP_GPIO>;
group0 {
pinmux = <PB9MFP_UART1_nCTS>,
<PB8MFP_UART1_nRTS>,
<PB2MFP_UART1_RXD>,
<PB3MFP_UART1_TXD>,
<PC9MFP_GPIO>;
};
};
};
37 changes: 32 additions & 5 deletions drivers/pinctrl/pinctrl_numaker.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,54 @@
#include <zephyr/drivers/pinctrl.h>
#include <NuMicro.h>

/* Get mfp_base, it should be == (&SYS->GPA_MFP0) */
#define MFP_BASE DT_INST_REG_ADDR_BY_NAME(0, mfp)
#define MFOS_BASE DT_INST_REG_ADDR_BY_NAME(0, mfos)
#define GPA_BASE DT_REG_ADDR(DT_NODELABEL(gpioa))
#define GPIO_SIZE DT_REG_SIZE(DT_NODELABEL(gpioa))

#define SLEWCTL_PIN_SHIFT(pin_idx) ((pin_idx) * 2)
#define SLEWCTL_MASK(pin_idx) (3 << SLEWCTL_PIN_SHIFT(pin_idx))

static void gpio_configure(const pinctrl_soc_pin_t *pin, uint8_t port_idx, uint8_t pin_idx)
{
GPIO_T *port;

port = (GPIO_T *)(GPA_BASE + port_idx * GPIO_SIZE);

port->SMTEN = (port->SMTEN & ~BIT(pin_idx)) |
((pin->schmitt_enable ? 1 : 0) << pin_idx);
port->SLEWCTL = (port->SLEWCTL & ~SLEWCTL_MASK(pin_idx)) |
(pin->slew_rate << SLEWCTL_PIN_SHIFT(pin_idx));

}
/**
* Configure pin multi-function
*/
static void configure_pin(const pinctrl_soc_pin_t *pin)
{
uint32_t pin_mux = pin->pin_mux;
uint32_t pin_index = PIN_INDEX(pin_mux);
uint32_t port_index = PORT_INDEX(pin_mux);
uint8_t pin_index = PIN_INDEX(pin_mux);
uint8_t port_index = PORT_INDEX(pin_mux);
uint32_t mfp_cfg = MFP_CFG(pin_mux);

/* Get mfp_base, it should be == (&SYS->GPA_MFP0) in M467 */
uint32_t mfp_base = DT_REG_ADDR(DT_NODELABEL(pinctrl));

uint32_t *GPx_MFPx = ((uint32_t *)mfp_base) + port_index * 4 + (pin_index / 4);
uint32_t *GPx_MFPx = ((uint32_t *)MFP_BASE) + port_index * 4 + (pin_index / 4);
uint32_t *GPx_MFOSx = ((uint32_t *)MFOS_BASE) + port_index;
uint32_t pinMask = NU_MFP_MASK(pin_index);

/*
* E.g.: SYS->GPA_MFP0 = (SYS->GPA_MFP0 & (~SYS_GPA_MFP0_PA0MFP_Msk) ) |
* SYS_GPA_MFP0_PA0MFP_SC0_CD;
*/
*GPx_MFPx = (*GPx_MFPx & (~pinMask)) | mfp_cfg;
if (pin->open_drain != 0) {
*GPx_MFOSx |= BIT(pin_index);
} else {
*GPx_MFOSx &= ~BIT(pin_index);
}

gpio_configure(pin, port_index, pin_index);
}

/* Pinctrl API implementation */
Expand Down
6 changes: 4 additions & 2 deletions dts/arm/nuvoton/m46x.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,11 @@
status = "disabled";
};

pinctrl: pin-controller@40000500 {
pinctrl: pin-controller@40000080 {
compatible = "nuvoton,numaker-pinctrl";
reg = <0x40000500 0xa0>;
reg = <0x40000080 0x28
0x40000500 0xa0>;
reg-names = "mfos", "mfp";
status = "okay";
};

Expand Down
85 changes: 45 additions & 40 deletions dts/bindings/pinctrl/nuvoton,numaker-pinctrl.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ description: |
/* configuration for the uart0 "default" state */
uart0_default: uart0_default {
/* configure PB13 as UART0 TX and PB12 as UART0 RX */
pinmux = <PB12MFP_UART0_RXD 0x0000>, <PB13MFP_UART0_TXD 0x0000>;
group0 {
pinmux = <PB12MFP_UART0_RXD>, <PB13MFP_UART0_TXD>;
};
};
};
Expand All @@ -37,44 +39,47 @@ description: |
compatible: "nuvoton,numaker-pinctrl"

include:
- name: base.yaml
- name: pincfg-node.yaml
child-binding:
property-allowlist:
- drive-push-pull
- drive-open-drain
- bias-disable
- bias-pull-down
- bias-pull-up
include: base.yaml

properties:
reg:
required: true

child-binding:
description: |
Each child node defines the configuration for a particular state.
properties:
pinmux:
required: true
type: array
description: |
An array of pins sharing the same group properties. The pins should
be defined using pre-defined macros or, alternatively, using NVT_PINMUX
macros depending on the pinmux model used by the SoC series.
drive-strength:
type: string
default: "low"
enum:
- "low"
- "fast"
description: |
Set the driving strength of a pin. Hardware default configuration is low and
it's enough to drive most components, like as LED, CAN transceiver and so on.
slew-rate:
type: string
default: "low"
enum:
- "fast"
- "low"
description: |
Set the speed of a pin. This setting effectively limits the
slew rate of the output signal. Hardware default configuration is low.
Fast slew rate could support high speed pins, like as SPI CLK up to 50MHz.
description: NuMaker pin controller pin group
child-binding:
description: |
Each child node defines the configuration for a particular state.
include:
- name: pincfg-node.yaml
property-allowlist:
- drive-open-drain
- input-schmitt-enable
properties:
pinmux:
required: true
type: array
description: |
An array of pins sharing the same group properties. The pins should
be defined using pre-defined macros or, alternatively, using NVT_PINMUX
macros depending on the pinmux model used by the SoC series.
drive-strength:
type: string
default: "low"
enum:
- "low"
- "fast"
description: |
Set the driving strength of a pin. Hardware default configuration is low and
it's enough to drive most components, like as LED, CAN transceiver and so on.
slew-rate:
type: string
default: "low"
enum:
- "low"
- "high"
- "fast"
description: |
Set the speed of a pin. This setting effectively limits the
slew rate of the output signal. Hardware default configuration is low.
Fast slew rate could support fast speed pins, like as SPI CLK up to 50MHz.
32 changes: 24 additions & 8 deletions soc/arm/nuvoton_numaker/common/pinctrl_soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,37 @@

#define PORT_INDEX(pinmux) (((pinmux)&0xF0000000) >> 28)
#define PIN_INDEX(pinmux) (((pinmux)&0x0F000000) >> 24)
#define MFP_CFG(pinmux) (((pinmux)&0x000000FF) << ((PIN_INDEX(pinmux) % 4) * 8))
#define MFP_CFG(pinmux) (((pinmux)&0x000000FF) << ((PIN_INDEX(pinmux) % 4) * 8))
#define NU_MFP_POS(pinindex) ((pinindex % 4) * 8)
#define NU_MFP_MASK(pinindex) (0x1f << NU_MFP_POS(pinindex))

#ifdef __cplusplus
extern "C" {
#endif

typedef struct pinctrl_soc_pin_t {
uint32_t pin_mux;
uint32_t open_drain: 1;
uint32_t schmitt_enable: 1;
uint32_t slew_rate: 2;
} pinctrl_soc_pin_t;

#define NUMAKER_DT_PIN(node_id, prop, idx) {.pin_mux = DT_PROP_BY_IDX(node_id, prop, idx)},

#define Z_PINCTRL_STATE_PIN_INIT(node_id, prop, idx) NUMAKER_DT_PIN(node_id, prop, idx)

#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \
{ \
DT_FOREACH_PROP_ELEM(DT_PHANDLE(node_id, prop), pinmux, Z_PINCTRL_STATE_PIN_INIT) \
#define Z_PINCTRL_STATE_PIN_INIT(node_id, prop, idx) \
{ \
.pin_mux = DT_PROP_BY_IDX(node_id, prop, idx), \
.open_drain = DT_PROP(node_id, drive_open_drain), \
.schmitt_enable = DT_PROP(node_id, input_schmitt_enable), \
.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) \
}

#ifdef __cplusplus
}
#endif

#endif /* _NUVOTON_NUMAKER_PINCTRL_SOC_H_ */

0 comments on commit 4894d9d

Please sign in to comment.