From 2070c0997f9bf0c108eb57be1101f16e05ceb7aa Mon Sep 17 00:00:00 2001 From: Scott Worley Date: Wed, 28 Jul 2021 09:52:00 -0400 Subject: [PATCH] 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 --- .../mec172xevb_assy6906_defconfig | 1 + boards/arm/mec172xevb_assy6906/pinmux.c | 106 ++++++++++++++- drivers/pinmux/pinmux_mchp_xec.c | 128 +++++------------- dts/arm/microchip/mec1501hsz.dtsi | 8 +- dts/arm/microchip/mec172xnsz.dtsi | 29 ++++ .../pinctrl/microchip,xec-pinmux.yaml | 9 ++ .../mec172x/Kconfig.defconfig.mec172xnsz | 4 + 7 files changed, 186 insertions(+), 99 deletions(-) diff --git a/boards/arm/mec172xevb_assy6906/mec172xevb_assy6906_defconfig b/boards/arm/mec172xevb_assy6906/mec172xevb_assy6906_defconfig index ebfe5b5eed6..926022b9c1d 100644 --- a/boards/arm/mec172xevb_assy6906/mec172xevb_assy6906_defconfig +++ b/boards/arm/mec172xevb_assy6906/mec172xevb_assy6906_defconfig @@ -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 diff --git a/boards/arm/mec172xevb_assy6906/pinmux.c b/boards/arm/mec172xevb_assy6906/pinmux.c index cfeeedb187a..eba7b952b73 100644 --- a/boards/arm/mec172xevb_assy6906/pinmux.c +++ b/boards/arm/mec172xevb_assy6906/pinmux.c @@ -9,9 +9,105 @@ #include #include -#include "soc.h" +#include -/* - * 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); diff --git a/drivers/pinmux/pinmux_mchp_xec.c b/drivers/pinmux/pinmux_mchp_xec.c index c7b8531d787..bf44cd77bd0 100644 --- a/drivers/pinmux/pinmux_mchp_xec.c +++ b/drivers/pinmux/pinmux_mchp_xec.c @@ -6,8 +6,12 @@ #include #include +#include #include #include +#include + +#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) diff --git a/dts/arm/microchip/mec1501hsz.dtsi b/dts/arm/microchip/mec1501hsz.dtsi index e8441b81efc..2a6c4b2dc1a 100644 --- a/dts/arm/microchip/mec1501hsz.dtsi +++ b/dts/arm/microchip/mec1501hsz.dtsi @@ -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>; }; }; diff --git a/dts/arm/microchip/mec172xnsz.dtsi b/dts/arm/microchip/mec172xnsz.dtsi index a4f102eab7f..82842e93359 100644 --- a/dts/arm/microchip/mec172xnsz.dtsi +++ b/dts/arm/microchip/mec172xnsz.dtsi @@ -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>; diff --git a/dts/bindings/pinctrl/microchip,xec-pinmux.yaml b/dts/bindings/pinctrl/microchip,xec-pinmux.yaml index 0dc12da3d25..b1c72e48b74 100644 --- a/dts/bindings/pinctrl/microchip,xec-pinmux.yaml +++ b/dts/bindings/pinctrl/microchip,xec-pinmux.yaml @@ -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. diff --git a/soc/arm/microchip_mec/mec172x/Kconfig.defconfig.mec172xnsz b/soc/arm/microchip_mec/mec172x/Kconfig.defconfig.mec172xnsz index 58506b0de2f..d2ee8515790 100644 --- a/soc/arm/microchip_mec/mec172x/Kconfig.defconfig.mec172xnsz +++ b/soc/arm/microchip_mec/mec172x/Kconfig.defconfig.mec172xnsz @@ -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