1 /*
2 * Copyright 2022 NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/drivers/pinctrl.h>
8 #include <soc.h>
9
10 static MCI_IO_MUX_Type *mci_iomux =
11 (MCI_IO_MUX_Type *)DT_REG_ADDR(DT_NODELABEL(pinctrl));
12
13 static SOCCIU_Type *soc_ctrl =
14 (SOCCIU_Type *)DT_REG_ADDR(DT_NODELABEL(soc_ctrl));
15 static AON_SOC_CIU_Type *aon_soc_ciu =
16 (AON_SOC_CIU_Type *)DT_REG_ADDR(DT_NODELABEL(aon_soc_ctrl));
17
18 /*
19 * GPIO mux option definitions. Stored as a static array, because
20 * these mux options are needed to clear pin mux settings to
21 * a known good state before selecting a new alternate function.
22 */
23 static uint64_t gpio_muxes[] = {IOMUX_GPIO_OPS};
24
25 /*
26 * Helper function to handle setting pin properties,
27 * such as pin bias and slew rate
28 */
configure_pin_props(uint32_t pin_mux,uint8_t gpio_idx)29 static void configure_pin_props(uint32_t pin_mux, uint8_t gpio_idx)
30 {
31 uint32_t mask, set;
32 volatile uint32_t *pull_reg = &soc_ctrl->PAD_PU_PD_EN0;
33 volatile uint32_t *slew_reg = &soc_ctrl->SR_CONFIG0;
34 volatile uint32_t *sleep_force_en = &soc_ctrl->PAD_SLP_EN0;
35 volatile uint32_t *sleep_force_val = &soc_ctrl->PAD_SLP_VAL0;
36
37 /* GPIO 22-27 use always on configuration registers */
38 if (gpio_idx > 21 && gpio_idx < 28) {
39 pull_reg = (&aon_soc_ciu->PAD_PU_PD_EN1 - 1);
40 slew_reg = (&aon_soc_ciu->SR_CONFIG1 - 1);
41 sleep_force_en = &aon_soc_ciu->PAD_SLP_EN0;
42 sleep_force_val = &aon_soc_ciu->PAD_SLP_VAL0;
43 }
44 /* Calculate register offset for pull and slew regs.
45 * Use bit shifting as opposed to division
46 */
47 pull_reg += (gpio_idx >> 4);
48 slew_reg += (gpio_idx >> 4);
49 sleep_force_en += (gpio_idx >> 5);
50 sleep_force_val += (gpio_idx >> 5);
51 /* Set pull-up/pull-down */
52 /* Use mask and bitshift here as opposed to modulo and multiplication.
53 * equivalent to ((gpio_idx % 16) * 2)
54 */
55 mask = 0x3 << ((gpio_idx & 0xF) << 1);
56 set = IOMUX_PAD_GET_PULL(pin_mux) << ((gpio_idx & 0xF) << 1);
57 *pull_reg = (*pull_reg & ~mask) | set;
58
59 /* Set slew rate */
60 set = IOMUX_PAD_GET_SLEW(pin_mux) << ((gpio_idx & 0xF) << 1);
61 *slew_reg = (*slew_reg & ~mask) | set;
62
63 /* Set sleep force enable bit */
64 mask = (0x1 << (gpio_idx & 0x1F));
65 set = (IOMUX_PAD_GET_SLEEP_FORCE_EN(pin_mux) << (gpio_idx & 0x1F));
66 *sleep_force_en = (*sleep_force_en & ~mask) | set;
67 set = (IOMUX_PAD_GET_SLEEP_FORCE_VAL(pin_mux) << (gpio_idx & 0x1F));
68 *sleep_force_val = (*sleep_force_val & ~mask) | set;
69 }
70
select_gpio_mode(uint8_t gpio_idx)71 static void select_gpio_mode(uint8_t gpio_idx)
72 {
73 uint64_t gpio_setting = gpio_muxes[gpio_idx];
74 volatile uint32_t *flexcomm_reg = &mci_iomux->FC0;
75
76 /* Clear flexcomm settings */
77 flexcomm_reg += IOMUX_GET_FLEXCOMM_CLR_IDX(gpio_setting);
78 *flexcomm_reg &= ~IOMUX_GET_FLEXCOMM_CLR_MASK(gpio_setting);
79 /* Clear fsel settings */
80 mci_iomux->FSEL &= ~IOMUX_GET_FSEL_CLR_MASK(gpio_setting);
81 /* Clear CTimer in/out, if required */
82 if (IOMUX_GET_SCTIMER_IN_CLR_ENABLE(gpio_setting)) {
83 mci_iomux->C_TIMER_IN &=
84 ~(0x1 << IOMUX_GET_CTIMER_CLR_OFFSET(gpio_setting));
85 mci_iomux->C_TIMER_OUT &=
86 ~(0x1 << IOMUX_GET_CTIMER_CLR_OFFSET(gpio_setting));
87 }
88 /* Clear SCTimer in/out, if required */
89 if (IOMUX_GET_SCTIMER_IN_CLR_ENABLE(gpio_setting)) {
90 mci_iomux->SC_TIMER &=
91 ~(0x1 << IOMUX_GET_SCTIMER_IN_CLR_OFFSET(gpio_setting));
92 }
93 if (IOMUX_GET_SCTIMER_OUT_CLR_ENABLE(gpio_setting)) {
94 mci_iomux->SC_TIMER &=
95 ~(0x1 << (IOMUX_GET_SCTIMER_OUT_CLR_OFFSET(gpio_setting) + 16));
96 }
97 /* Clear security gpio enable */
98 mci_iomux->S_GPIO &= ~(0x1 << (gpio_idx - 32));
99 }
100
101
pinctrl_configure_pins(const pinctrl_soc_pin_t * pins,uint8_t pin_cnt,uintptr_t reg)102 int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt,
103 uintptr_t reg)
104 {
105 volatile uint32_t *flexcomm_reg;
106 volatile uint32_t *iomux_en_reg;
107
108 for (uint8_t i = 0; i < pin_cnt; i++) {
109 flexcomm_reg = &mci_iomux->FC0;
110 iomux_en_reg = &soc_ctrl->MCI_IOMUX_EN0;
111 uint32_t pin_mux = pins[i];
112 uint8_t gpio_idx = IOMUX_GET_GPIO_IDX(pin_mux);
113 uint8_t type = IOMUX_GET_TYPE(pin_mux);
114 /*
115 * Before selecting an alternate function, we must clear any
116 * conflicting pin configuration. We do this by resetting the
117 * pin to a gpio configuration, then selecting the alternate
118 * function.
119 */
120 select_gpio_mode(gpio_idx);
121 switch (type) {
122 case IOMUX_FLEXCOMM:
123 flexcomm_reg += IOMUX_GET_FLEXCOMM_IDX(pin_mux);
124 *flexcomm_reg |=
125 (0x1 << IOMUX_GET_FLEXCOMM_BIT(pin_mux));
126 break;
127 case IOMUX_FSEL:
128 mci_iomux->FSEL |=
129 (0x1 << IOMUX_GET_FSEL_BIT(pin_mux));
130 break;
131 case IOMUX_CTIMER_IN:
132 mci_iomux->C_TIMER_IN |=
133 (0x1 << IOMUX_GET_CTIMER_BIT(pin_mux));
134 break;
135 case IOMUX_CTIMER_OUT:
136 mci_iomux->C_TIMER_OUT |=
137 (0x1 << IOMUX_GET_CTIMER_BIT(pin_mux));
138 break;
139 case IOMUX_SCTIMER_IN:
140 mci_iomux->SC_TIMER |=
141 (0x1 << IOMUX_GET_SCTIMER_BIT(pin_mux));
142 break;
143 case IOMUX_SCTIMER_OUT:
144 mci_iomux->SC_TIMER |=
145 (0x1 << (IOMUX_GET_SCTIMER_BIT(pin_mux) + 16));
146 break;
147 case IOMUX_SGPIO:
148 mci_iomux->S_GPIO |= (0x1 << (gpio_idx - 32));
149 break;
150 case IOMUX_GPIO:
151 if (gpio_idx > 32) {
152 mci_iomux->GPIO_GRP1 |= (0x1 << (gpio_idx - 32));
153 } else {
154 mci_iomux->GPIO_GRP0 |= (0x1 << gpio_idx);
155 }
156 break;
157 case IOMUX_AON:
158 /* No selection bits should be set */
159 break;
160 default:
161 /* Unsupported type passed */
162 return -ENOTSUP;
163 }
164 configure_pin_props(pin_mux, gpio_idx);
165 /* Now, enable pin controller access to this pin */
166 if (gpio_idx > 21 && gpio_idx < 28) {
167 /* GPIO 22-27 use always on soc controller */
168 iomux_en_reg = &aon_soc_ciu->MCI_IOMUX_EN0;
169 }
170 iomux_en_reg += (gpio_idx >> 5);
171 *iomux_en_reg |= (0x1 << (gpio_idx & 0x1F));
172 }
173 return 0;
174 }
175