1 /*
2  * Copyright (c) 2022-2023, Gerson Fernando Budke <nandojve@gmail.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/drivers/pinctrl.h>
8 #include <zephyr/drivers/clock_control/atmel_sam_pmc.h>
9 #include <soc_gpio.h>
10 
11 /** Utility macro that expands to the GPIO port address if it exists */
12 #define SAM_PORT_ADDR_OR_NONE(nodelabel)					\
13 	IF_ENABLED(DT_NODE_EXISTS(DT_NODELABEL(nodelabel)),			\
14 		   (DT_REG_ADDR(DT_NODELABEL(nodelabel)),))
15 
16 /** Utility macro that expands to the GPIO Peripheral ID if it exists */
17 #define SAM_PORT_CLOCKS_OR_NONE(nodelabel)					\
18 	IF_ENABLED(DT_NODE_EXISTS(DT_NODELABEL(nodelabel)),			\
19 		   (SAM_DT_CLOCK_PMC_CFG(0, DT_NODELABEL(nodelabel)),))
20 
21 /** SAM port addresses */
22 static const uint32_t sam_port_addrs[] = {
23 #ifdef ID_GPIO
24 	SAM_PORT_ADDR_OR_NONE(gpioa)
25 	SAM_PORT_ADDR_OR_NONE(gpiob)
26 	SAM_PORT_ADDR_OR_NONE(gpioc)
27 #else
28 	SAM_PORT_ADDR_OR_NONE(pioa)
29 	SAM_PORT_ADDR_OR_NONE(piob)
30 	SAM_PORT_ADDR_OR_NONE(pioc)
31 	SAM_PORT_ADDR_OR_NONE(piod)
32 	SAM_PORT_ADDR_OR_NONE(pioe)
33 	SAM_PORT_ADDR_OR_NONE(piof)
34 #endif
35 };
36 
37 /** SAM port clocks */
38 static const struct atmel_sam_pmc_config sam_port_clocks[] = {
39 #ifdef ID_GPIO
40 	SAM_PORT_CLOCKS_OR_NONE(gpioa)
41 	SAM_PORT_CLOCKS_OR_NONE(gpiob)
42 	SAM_PORT_CLOCKS_OR_NONE(gpioc)
43 #else
44 	SAM_PORT_CLOCKS_OR_NONE(pioa)
45 	SAM_PORT_CLOCKS_OR_NONE(piob)
46 	SAM_PORT_CLOCKS_OR_NONE(pioc)
47 	SAM_PORT_CLOCKS_OR_NONE(piod)
48 	SAM_PORT_CLOCKS_OR_NONE(pioe)
49 	SAM_PORT_CLOCKS_OR_NONE(piof)
50 #endif
51 };
52 
pinctrl_configure_pin(pinctrl_soc_pin_t pin)53 static void pinctrl_configure_pin(pinctrl_soc_pin_t pin)
54 {
55 	struct soc_gpio_pin soc_pin;
56 	uint8_t  port_idx, port_func;
57 
58 	port_idx = SAM_PINMUX_PORT_GET(pin);
59 	__ASSERT_NO_MSG(port_idx < ARRAY_SIZE(sam_port_addrs));
60 	port_func = SAM_PINMUX_FUNC_GET(pin);
61 
62 #ifdef ID_GPIO
63 	soc_pin.regs = (Gpio *) sam_port_addrs[port_idx];
64 #else
65 	soc_pin.regs = (Pio *) sam_port_addrs[port_idx];
66 #endif
67 	soc_pin.periph_id = sam_port_clocks[port_idx].peripheral_id;
68 	soc_pin.mask = 1 << SAM_PINMUX_PIN_GET(pin);
69 	soc_pin.flags = SAM_PINCTRL_FLAGS_GET(pin) << SOC_GPIO_FLAGS_POS;
70 
71 	if (port_func == SAM_PINMUX_FUNC_periph) {
72 		soc_pin.flags |= (SAM_PINMUX_PERIPH_GET(pin)
73 				  << SOC_GPIO_FUNC_POS);
74 	}
75 
76 	soc_gpio_configure(&soc_pin);
77 }
78 
pinctrl_configure_pins(const pinctrl_soc_pin_t * pins,uint8_t pin_cnt,uintptr_t reg)79 int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt,
80 			   uintptr_t reg)
81 {
82 	ARG_UNUSED(reg);
83 
84 	for (uint8_t i = 0U; i < pin_cnt; i++) {
85 		pinctrl_configure_pin(*pins++);
86 	}
87 
88 	return 0;
89 }
90