1 /*
2  * Copyright (c) 2022 Schlumberger
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT infineon_xmc4xxx_pinctrl
8 
9 #include <zephyr/devicetree.h>
10 #include <zephyr/drivers/pinctrl.h>
11 #include <zephyr/dt-bindings/pinctrl/xmc4xxx-pinctrl.h>
12 
13 #include <xmc_gpio.h>
14 
15 #define GPIO_REG_SIZE 0x100
16 
pinctrl_configure_pin(const pinctrl_soc_pin_t pinmux)17 static int pinctrl_configure_pin(const pinctrl_soc_pin_t pinmux)
18 {
19 	int port_id, pin, alt_fun, hwctrl;
20 	XMC_GPIO_CONFIG_t pin_cfg = {0};
21 	XMC_GPIO_PORT_t *gpio_port;
22 
23 	port_id = XMC4XXX_PINMUX_GET_PORT(pinmux);
24 	if (port_id >= DT_INST_REG_SIZE(0) / GPIO_REG_SIZE) {
25 		return -EINVAL;
26 	}
27 
28 	pin = XMC4XXX_PINMUX_GET_PIN(pinmux);
29 
30 	if (XMC4XXX_PINMUX_GET_PULL_DOWN(pinmux)) {
31 		pin_cfg.mode = XMC_GPIO_MODE_INPUT_PULL_DOWN;
32 	}
33 
34 	if (XMC4XXX_PINMUX_GET_PULL_UP(pinmux)) {
35 		pin_cfg.mode = XMC_GPIO_MODE_INPUT_PULL_UP;
36 	}
37 
38 	if (XMC4XXX_PINMUX_GET_INV_INPUT(pinmux)) {
39 		pin_cfg.mode |= 0x4;
40 	}
41 
42 	if (XMC4XXX_PINMUX_GET_OPEN_DRAIN(pinmux)) {
43 		pin_cfg.mode = XMC_GPIO_MODE_OUTPUT_OPEN_DRAIN;
44 	}
45 
46 	if (XMC4XXX_PINMUX_GET_PUSH_PULL(pinmux)) {
47 		pin_cfg.mode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL;
48 	}
49 
50 	alt_fun = XMC4XXX_PINMUX_GET_ALT(pinmux);
51 	pin_cfg.mode |= alt_fun << PORT0_IOCR0_PC0_Pos;
52 
53 	/* only has effect if mode is push_pull */
54 	if (XMC4XXX_PINMUX_GET_OUT_HIGH(pinmux)) {
55 		pin_cfg.output_level = XMC_GPIO_OUTPUT_LEVEL_HIGH;
56 	}
57 
58 	/* only has effect if mode is push_pull */
59 	if (XMC4XXX_PINMUX_GET_OUT_LOW(pinmux)) {
60 		pin_cfg.output_level = XMC_GPIO_OUTPUT_LEVEL_LOW;
61 	}
62 
63 	/* only has effect if mode is push_pull */
64 	pin_cfg.output_strength = XMC4XXX_PINMUX_GET_DRIVE(pinmux);
65 
66 	gpio_port = (XMC_GPIO_PORT_t *)((uint32_t)DT_INST_REG_ADDR(0) + port_id * GPIO_REG_SIZE);
67 	XMC_GPIO_Init(gpio_port, pin, &pin_cfg);
68 
69 	hwctrl = XMC4XXX_PINMUX_GET_HWCTRL(pinmux);
70 	if (hwctrl) {
71 		XMC_GPIO_SetHardwareControl(gpio_port, pin, hwctrl);
72 	}
73 
74 	return 0;
75 }
76 
pinctrl_configure_pins(const pinctrl_soc_pin_t * pins,uint8_t pin_cnt,uintptr_t reg)77 int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg)
78 {
79 	ARG_UNUSED(reg);
80 
81 	for (uint8_t i = 0U; i < pin_cnt; i++) {
82 		int ret = pinctrl_configure_pin(*pins++);
83 
84 		if (ret < 0) {
85 			return ret;
86 		}
87 	}
88 
89 	return 0;
90 }
91