Microchip: MEC172x: Update pinmux driver

Update the Microchip XEC pinmux driver to use system I/O
routine for read/write of registers instead of direct use
of volatile and CMSIS defines. Add GPIO port number to
bindings instead of using hard coded value from chip headers.
Modify SoC DTSI pinmux syntax, requires "pinmux: pinumx {..."
or the DT macros will not work. Since pinmux is used by MEC152x
we update its chip pinmux DT.

Signed-off-by: Scott Worley <scott.worley@microchip.com>
This commit is contained in:
Scott Worley 2021-07-28 09:52:00 -04:00 committed by Anas Nashif
commit 2070c0997f
7 changed files with 186 additions and 99 deletions

View file

@ -11,6 +11,7 @@ CONFIG_RTOS_TIMER=y
CONFIG_CLOCK_CONTROL=y
CONFIG_GPIO=y
CONFIG_PINMUX=y
CONFIG_SERIAL=y
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y

View file

@ -9,9 +9,105 @@
#include <kernel.h>
#include <drivers/pinmux.h>
#include "soc.h"
#include <soc.h>
/*
* If PINMUX will be used this is where board_pinmux_init should be implemented
* and added to SYS_INIT.
*/
#define XEC_UART_0_REGS \
((struct uart_regs *)DT_REG_ADDR(DT_NODELABEL(uart0)))
#define XEC_UART_1_REGS \
((struct uart_regs *)DT_REG_ADDR(DT_NODELABEL(uart1)))
struct pinmux_ports_t {
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_000_036), okay)
const struct device *porta;
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_040_076), okay)
const struct device *portb;
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_100_136), okay)
const struct device *portc;
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_140_176), okay)
const struct device *portd;
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_200_236), okay)
const struct device *porte;
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_240_276), okay)
const struct device *portf;
#endif
};
static void brd_init_pinmux_ports(struct pinmux_ports_t *pp)
{
ARG_UNUSED(pp);
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_000_036), okay)
pp->porta = DEVICE_DT_GET(DT_NODELABEL(pinmux_000_036));
__ASSERT_NO_MSG(device_is_ready(pp->porta));
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_040_076), okay)
pp->portb = DEVICE_DT_GET(DT_NODELABEL(pinmux_040_076));
__ASSERT_NO_MSG(device_is_ready(pp->portb));
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_100_136), okay)
pp->portc = DEVICE_DT_GET(DT_NODELABEL(pinmux_100_136));
__ASSERT_NO_MSG(device_is_ready(pp->portc));
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_140_176), okay)
pp->portd = DEVICE_DT_GET(DT_NODELABEL(pinmux_140_176));
__ASSERT_NO_MSG(device_is_ready(pp->portd));
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_200_236), okay)
pp->porte = DEVICE_DT_GET(DT_NODELABEL(pinmux_200_236));
__ASSERT_NO_MSG(device_is_ready(pp->porte));
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_240_276), okay)
pp->portf = DEVICE_DT_GET(DT_NODELABEL(pinmux_240_276));
__ASSERT_NO_MSG(device_is_ready(pp->portf));
#endif
}
static void brd_cfg_uart(struct pinmux_ports_t *pp)
{
#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart0), okay)
struct uart_regs *uart0 = XEC_UART_0_REGS;
uart0->CFG_SEL = (MCHP_UART_LD_CFG_INTCLK +
MCHP_UART_LD_CFG_RESET_SYS + MCHP_UART_LD_CFG_NO_INVERT);
uart0->ACTV = MCHP_UART_LD_ACTIVATE;
pinmux_pin_set(pp->portc, MCHP_GPIO_104, MCHP_GPIO_CTRL_MUX_F1);
pinmux_pin_set(pp->portc, MCHP_GPIO_105, MCHP_GPIO_CTRL_MUX_F1);
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart1), okay)
struct uart_regs *uart1 = XEC_UART_1_REGS;
uart1->CFG_SEL = (MCHP_UART_LD_CFG_INTCLK +
MCHP_UART_LD_CFG_RESET_SYS + MCHP_UART_LD_CFG_NO_INVERT);
uart1->ACTV = MCHP_UART_LD_ACTIVATE;
pinmux_pin_set(pp->portd, MCHP_GPIO_170, MCHP_GPIO_CTRL_MUX_F1);
pinmux_pin_set(pp->portd, MCHP_GPIO_171, MCHP_GPIO_CTRL_MUX_F1);
#endif
}
/* caller passes dev = NULL */
static int board_pinmux_init(const struct device *dev)
{
ARG_UNUSED(dev);
struct pinmux_ports_t pp;
brd_init_pinmux_ports(&pp);
brd_cfg_uart(&pp);
return 0;
}
SYS_INIT(board_pinmux_init, PRE_KERNEL_1, CONFIG_PINMUX_INIT_PRIORITY);

View file

@ -6,8 +6,12 @@
#include <errno.h>
#include <device.h>
#include <devicetree.h>
#include <drivers/pinmux.h>
#include <soc.h>
#include <sys/printk.h>
#define DT_DRV_COMPAT microchip_xec_pinmux
static const uint32_t valid_ctrl_masks[NUM_MCHP_GPIO_PORTS] = {
(MCHP_GPIO_PORT_A_BITMAP),
@ -19,7 +23,7 @@ static const uint32_t valid_ctrl_masks[NUM_MCHP_GPIO_PORTS] = {
};
struct pinmux_xec_config {
__IO uint32_t *pcr1_base;
uintptr_t pcr1_base;
uint32_t port_num;
};
@ -27,9 +31,10 @@ static int pinmux_xec_set(const struct device *dev, uint32_t pin,
uint32_t func)
{
const struct pinmux_xec_config *config = dev->config;
__IO uint32_t *current_pcr1;
uintptr_t current_pcr1;
uint32_t pcr1 = 0;
uint32_t mask = 0;
uint32_t temp = 0;
/* Validate pin number in terms of current port */
if ((valid_ctrl_masks[config->port_num] & BIT(pin)) == 0) {
@ -70,10 +75,12 @@ static int pinmux_xec_set(const struct device *dev, uint32_t pin,
mask |= MCHP_GPIO_CTRL_IDET_MASK;
/* Now write contents of pcr1 variable to the PCR1 register that
* corresponds to the pin configured
* corresponds to the pin configured. Each pin control register
* on a 32-bit boundary.
*/
current_pcr1 = config->pcr1_base + pin;
*current_pcr1 = (*current_pcr1 & ~mask) | pcr1;
current_pcr1 = config->pcr1_base + pin * 4;
temp = (sys_read32(current_pcr1) & ~mask) | pcr1;
sys_write32(temp, current_pcr1);
return 0;
}
@ -82,17 +89,17 @@ static int pinmux_xec_get(const struct device *dev, uint32_t pin,
uint32_t *func)
{
const struct pinmux_xec_config *config = dev->config;
__IO uint32_t *current_pcr1;
uintptr_t current_pcr1;
/* Validate pin number in terms of current port */
if ((valid_ctrl_masks[config->port_num] & BIT(pin)) == 0) {
return -EINVAL;
}
current_pcr1 = config->pcr1_base + pin;
*func = *current_pcr1 & (MCHP_GPIO_CTRL_BUFT_MASK
| MCHP_GPIO_CTRL_MUX_MASK
| MCHP_GPIO_CTRL_PUD_MASK);
current_pcr1 = config->pcr1_base + pin * 4;
*func = sys_read32(current_pcr1) & (MCHP_GPIO_CTRL_BUFT_MASK
| MCHP_GPIO_CTRL_MUX_MASK
| MCHP_GPIO_CTRL_PUD_MASK);
return 0;
}
@ -122,88 +129,23 @@ static const struct pinmux_driver_api pinmux_xec_driver_api = {
.input = pinmux_xec_input,
};
#define PINMUX_ADDR(n) DT_REG_ADDR(DT_PHANDLE(DT_NODELABEL(n), ph_reg))
/* Get ph_reg address given a node-id */
#define PINMUX_ADDR(n) DT_REG_ADDR(DT_PHANDLE(n, ph_reg))
/* Get ph_reg address given instance */
#define PINMUX_INST_ADDR(n) DT_REG_ADDR(DT_PHANDLE(DT_NODELABEL(n), ph_reg))
/* Get port-num property */
#define PINMUX_PORT_NUM(n) DT_PROP(DT_NODELABEL(n), port_num)
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_000_036), okay)
static const struct pinmux_xec_config pinmux_xec_port000_036_config = {
.pcr1_base = (uint32_t *) PINMUX_ADDR(pinmux_000_036),
.port_num = MCHP_GPIO_000_036,
};
/* id is a child node-id */
#define PINMUX_XEC_DEVICE(id) \
static const struct pinmux_xec_config pinmux_xec_port_cfg_##id = { \
.pcr1_base = (uintptr_t)PINMUX_ADDR(id), \
.port_num = (uint32_t)DT_PROP(id, port_num), \
}; \
DEVICE_DT_DEFINE(id, &pinmux_xec_init, NULL, NULL, \
&pinmux_xec_port_cfg_##id, \
PRE_KERNEL_1, \
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
&pinmux_xec_driver_api);
DEVICE_DT_DEFINE(DT_NODELABEL(pinmux_000_036),
&pinmux_xec_init,
NULL,
NULL, &pinmux_xec_port000_036_config,
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&pinmux_xec_driver_api);
#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_000_036), okay) */
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_040_076), okay)
static const struct pinmux_xec_config pinmux_xec_port040_076_config = {
.pcr1_base = (uint32_t *) PINMUX_ADDR(pinmux_040_076),
.port_num = MCHP_GPIO_040_076,
};
DEVICE_DT_DEFINE(DT_NODELABEL(pinmux_040_076),
&pinmux_xec_init,
NULL,
NULL, &pinmux_xec_port040_076_config,
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&pinmux_xec_driver_api);
#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_040_076), okay) */
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_100_136), okay)
static const struct pinmux_xec_config pinmux_xec_port100_136_config = {
.pcr1_base = (uint32_t *) PINMUX_ADDR(pinmux_100_136),
.port_num = MCHP_GPIO_100_136,
};
DEVICE_DT_DEFINE(DT_NODELABEL(pinmux_100_136),
&pinmux_xec_init,
NULL,
NULL, &pinmux_xec_port100_136_config,
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&pinmux_xec_driver_api);
#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_100_136), okay) */
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_140_176), okay)
static const struct pinmux_xec_config pinmux_xec_port140_176_config = {
.pcr1_base = (uint32_t *) PINMUX_ADDR(pinmux_140_176),
.port_num = MCHP_GPIO_140_176,
};
DEVICE_DT_DEFINE(DT_NODELABEL(pinmux_140_176),
&pinmux_xec_init,
NULL,
NULL, &pinmux_xec_port140_176_config,
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&pinmux_xec_driver_api);
#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_140_176), okay) */
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_200_236), okay)
static const struct pinmux_xec_config pinmux_xec_port200_236_config = {
.pcr1_base = (uint32_t *) PINMUX_ADDR(pinmux_200_236),
.port_num = MCHP_GPIO_200_236,
};
DEVICE_DT_DEFINE(DT_NODELABEL(pinmux_200_236),
&pinmux_xec_init,
NULL,
NULL, &pinmux_xec_port200_236_config,
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&pinmux_xec_driver_api);
#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_200_236), okay) */
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_240_276), okay)
static const struct pinmux_xec_config pinmux_xec_port240_276_config = {
.pcr1_base = (uint32_t *) PINMUX_ADDR(pinmux_240_276),
.port_num = MCHP_GPIO_240_276,
};
DEVICE_DT_DEFINE(DT_NODELABEL(pinmux_240_276),
&pinmux_xec_init,
NULL,
NULL, &pinmux_xec_port240_276_config,
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&pinmux_xec_driver_api);
#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(pinmux_240_276), okay) */
DT_FOREACH_CHILD_STATUS_OKAY(DT_NODELABEL(pinmux), PINMUX_XEC_DEVICE)

View file

@ -37,26 +37,32 @@
i2c-smb-4 = &i2c_smb_4;
};
pinmux {
pinmux: pinmux {
compatible = "microchip,xec-pinmux";
pinmux_000_036: pinmux-0 {
ph-reg = <&gpio_000_036>;
port-num = <0>;
};
pinmux_040_076: pinmux-1 {
ph-reg = <&gpio_040_076>;
port-num = <1>;
};
pinmux_100_136: pinmux-2 {
ph-reg = <&gpio_100_136>;
port-num = <2>;
};
pinmux_140_176: pinmux-3 {
ph-reg = <&gpio_140_176>;
port-num = <3>;
};
pinmux_200_236: pinmux-4 {
ph-reg = <&gpio_200_236>;
port-num = <4>;
};
pinmux_240_276: pinmux-5 {
ph-reg = <&gpio_240_276>;
port-num = <5>;
};
};

View file

@ -32,6 +32,35 @@
reg = <0x00118000 0x10000>;
};
pinmux: pinmux {
compatible = "microchip,xec-pinmux";
pinmux_000_036: pinmux-0 {
ph-reg = <&gpio_000_036>;
port-num = <0>;
};
pinmux_040_076: pinmux-1 {
ph-reg = <&gpio_040_076>;
port-num = <1>;
};
pinmux_100_136: pinmux-2 {
ph-reg = <&gpio_100_136>;
port-num = <2>;
};
pinmux_140_176: pinmux-3 {
ph-reg = <&gpio_140_176>;
port-num = <3>;
};
pinmux_200_236: pinmux-4 {
ph-reg = <&gpio_200_236>;
port-num = <4>;
};
pinmux_240_276: pinmux-5 {
ph-reg = <&gpio_240_276>;
port-num = <5>;
};
};
soc {
ecs: ecs@4000fc00 {
reg = <0x4000fc00 0x200>;

View file

@ -4,9 +4,18 @@ description: Microchip XEC Pinmux node
compatible: "microchip,xec-pinmux"
include: base.yaml
child-binding:
description: pinmux child node
properties:
ph-reg:
type: phandle
required: true
port-num:
type: int
required: true
description: |
Zero based GPIO port number. Pin group 000 - 036 is port 0,
040 - 076 is port 1, etc.

View file

@ -19,4 +19,8 @@ config GPIO_XEC_V2
default y
depends on GPIO
config PINMUX_XEC
default y
depends on PINMUX
endif # SOC_MEC172X_NSZ