1 /*
2  * Copyright (c) 2022, NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_SOC_ARM_NXP_IMX_RT_PINCTRL_RT11XX_H_
8 #define ZEPHYR_SOC_ARM_NXP_IMX_RT_PINCTRL_RT11XX_H_
9 
10 #include <zephyr/devicetree.h>
11 #include <zephyr/types.h>
12 #include "fsl_common.h"
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 #define MCUX_IMX_ODE_SHIFT 4
19 #define MCUX_IMX_PUS_SHIFT 3
20 #define MCUX_IMX_PUE_SHIFT 2
21 #define MCUX_IMX_DSE_SHIFT 1
22 #define MCUX_IMX_SRE_SHIFT 0
23 #define MCUX_IMX_PULL_SHIFT 2
24 #define MCUX_IMX_PULL_PULLDOWN 0x2
25 #define MCUX_IMX_PULL_PULLUP 0x1
26 #define MCUX_IMX_PDRV_SHIFT 1
27 #define MCUX_IMX_LPSR_ODE_SHIFT 5
28 #define MCUX_IMX_SNVS_ODE_SHIFT 6
29 #define MCUX_IMX_INPUT_ENABLE_SHIFT 31 /* Shift to a bit not used by IOMUXC_SW_PAD_CTL */
30 #define MCUX_IMX_INPUT_ENABLE(x) ((x >> MCUX_IMX_INPUT_ENABLE_SHIFT) & 0x1)
31 
32 
33 /*
34  * RT11xx has multiple types of register layouts defined for pin configuration
35  * registers. There are four types defined:
36  * pdrv_pull: registers lack a slew rate and pus field
37  * pue_pus: registers have a slew rate and ode field
38  * pue_pus_lpsr: in low power state retention domain, shifted ode field
39  * pue_pus_snvs: in SNVS domain, shifted ode field
40  */
41 
42 #define MCUX_IMX_PUS_PUE 0
43 #define MCUX_IMX_PDRV_PULL 1
44 #define MCUX_IMX_LPSR 2
45 #define MCUX_IMX_SNVS 3
46 
47 /*
48  * Macro for MCUX_IMX_PULL_NOPULL, which needs to set field to 0x3 if two
49  * properties are false
50  */
51 #define MCUX_IMX_NOPULL(node_id)								\
52 	((0x2 & ((!DT_PROP(node_id, bias_pull_down) && !DT_PROP(node_id, bias_pull_up)) << 1)) |\
53 	(0x1 & ((!DT_PROP(node_id, bias_pull_down) && !DT_PROP(node_id, bias_pull_up)) << 0)))	\
54 
55 #define Z_PINCTRL_MCUX_IMX_PDRV(node_id)							\
56 	IF_ENABLED(DT_PROP(node_id, bias_pull_down),						\
57 		(MCUX_IMX_PULL_PULLDOWN << MCUX_IMX_PULL_SHIFT) |)				\
58 	IF_ENABLED(DT_PROP(node_id, bias_pull_up),						\
59 		(MCUX_IMX_PULL_PULLUP << MCUX_IMX_PULL_SHIFT) |)				\
60 	(MCUX_IMX_NOPULL(node_id) << MCUX_IMX_PULL_SHIFT) |					\
61 	(DT_ENUM_IDX_OR(node_id, drive_strength, 0) << MCUX_IMX_PDRV_SHIFT) |			\
62 	(DT_PROP(node_id, drive_open_drain) << MCUX_IMX_ODE_SHIFT) |				\
63 	(DT_PROP(node_id, input_enable) << MCUX_IMX_INPUT_ENABLE_SHIFT)
64 
65 #define Z_PINCTRL_MCUX_IMX_PUE_PUS(node_id)							\
66 	(DT_PROP(node_id, bias_pull_up) << MCUX_IMX_PUS_SHIFT) |				\
67 	((DT_PROP(node_id, bias_pull_up) || DT_PROP(node_id, bias_pull_down))			\
68 		<< MCUX_IMX_PUE_SHIFT) |							\
69 	(DT_ENUM_IDX_OR(node_id, drive_strength, 0) << MCUX_IMX_DSE_SHIFT) |			\
70 	(DT_ENUM_IDX_OR(node_id, slew_rate, 0) << MCUX_IMX_SRE_SHIFT) |				\
71 	(DT_PROP(node_id, drive_open_drain) << MCUX_IMX_ODE_SHIFT) |				\
72 	(DT_PROP(node_id, input_enable) << MCUX_IMX_INPUT_ENABLE_SHIFT)
73 
74 #define Z_PINCTRL_MCUX_IMX_LPSR(node_id)							\
75 	(DT_PROP(node_id, bias_pull_up) << MCUX_IMX_PUS_SHIFT) |				\
76 	((DT_PROP(node_id, bias_pull_up) || DT_PROP(node_id, bias_pull_down))			\
77 		<< MCUX_IMX_PUE_SHIFT) |							\
78 	(DT_ENUM_IDX_OR(node_id, drive_strength, 0) << MCUX_IMX_DSE_SHIFT) |			\
79 	(DT_ENUM_IDX_OR(node_id, slew_rate, 0) << MCUX_IMX_SRE_SHIFT) |				\
80 	(DT_PROP(node_id, drive_open_drain) << MCUX_IMX_LPSR_ODE_SHIFT) |			\
81 	(DT_PROP(node_id, input_enable) << MCUX_IMX_INPUT_ENABLE_SHIFT)
82 
83 #define Z_PINCTRL_MCUX_IMX_SNVS(node_id)							\
84 	(DT_PROP(node_id, bias_pull_up) << MCUX_IMX_PUS_SHIFT) |				\
85 	((DT_PROP(node_id, bias_pull_up) || DT_PROP(node_id, bias_pull_down))			\
86 		<< MCUX_IMX_PUE_SHIFT) |							\
87 	(DT_ENUM_IDX_OR(node_id, drive_strength, 0) << MCUX_IMX_DSE_SHIFT) |			\
88 	(DT_ENUM_IDX_OR(node_id, slew_rate, 0) << MCUX_IMX_SRE_SHIFT) |				\
89 	(DT_PROP(node_id, drive_open_drain) << MCUX_IMX_SNVS_ODE_SHIFT) |			\
90 	(DT_PROP(node_id, input_enable) << MCUX_IMX_INPUT_ENABLE_SHIFT)
91 
92 /* This struct must be present. It is used by the mcux gpio driver */
93 struct pinctrl_soc_pinmux {
94 	uint32_t mux_register; /* IOMUXC SW_PAD_MUX register */
95 	uint32_t config_register; /* IOMUXC SW_PAD_CTL register */
96 	uint32_t input_register; /* IOMUXC SELECT_INPUT DAISY register */
97 	uint32_t gpr_register; /* IOMUXC GPR register */
98 	uint8_t gpr_shift: 5; /* bitshift  for GPR register write */
99 	uint8_t mux_mode: 4; /* Mux value for SW_PAD_MUX register */
100 	uint32_t input_daisy:4; /* Mux value for SELECT_INPUT_DAISY register */
101 	uint8_t gpr_val: 1; /* value to write to GPR register */
102 	uint8_t pue_mux: 1; /* Is pinmux reg pue type */
103 	uint8_t pdrv_mux: 1; /* Is pinmux reg pdrv type */
104 	uint8_t lpsr_mux: 1; /* Is pinmux reg LPSR type */
105 	uint8_t snvs_mux: 1; /* Is pinmux reg SNVS type */
106 };
107 
108 struct pinctrl_soc_pin {
109 	struct pinctrl_soc_pinmux pinmux;
110 	uint32_t pin_ctrl_flags; /* value to write to IOMUXC_SW_PAD_CTL register */
111 };
112 
113 typedef struct pinctrl_soc_pin pinctrl_soc_pin_t;
114 
115 /* This definition must be present. It is used by the mcux gpio driver */
116 #define MCUX_IMX_PINMUX(node_id)						\
117 	{									\
118 	  .mux_register = DT_PROP_BY_IDX(node_id, pinmux, 0),			\
119 	  .config_register = DT_PROP_BY_IDX(node_id, pinmux, 4),		\
120 	  .input_register = DT_PROP_BY_IDX(node_id, pinmux, 2),			\
121 	  .mux_mode = DT_PROP_BY_IDX(node_id, pinmux, 1),			\
122 	  .input_daisy = DT_PROP_BY_IDX(node_id, pinmux, 3),			\
123 	  IF_ENABLED(DT_PROP_HAS_IDX(node_id, gpr, 0),				\
124 	    (.gpr_register = DT_PROP_BY_IDX(node_id, gpr, 0),))			\
125 	  IF_ENABLED(DT_PROP_HAS_IDX(node_id, gpr, 1),				\
126 	    (.gpr_shift = DT_PROP_BY_IDX(node_id, gpr, 1),))			\
127 	  IF_ENABLED(DT_PROP_HAS_IDX(node_id, gpr, 2),				\
128 	    (.gpr_val = DT_PROP_BY_IDX(node_id, gpr, 2),))			\
129 	  .pue_mux = DT_PROP(node_id, pin_pue),					\
130 	  .pdrv_mux = DT_PROP(node_id, pin_pdrv),				\
131 	  .lpsr_mux = DT_PROP(node_id, pin_lpsr),				\
132 	  .snvs_mux = DT_PROP(node_id, pin_snvs),				\
133 	}
134 
135 #define Z_PINCTRL_PINMUX(group_id, pin_prop, idx)				\
136 	MCUX_IMX_PINMUX(DT_PHANDLE_BY_IDX(group_id, pin_prop, idx))
137 
138 #define Z_PINCTRL_STATE_PIN_INIT(group_id, pin_prop, idx)			\
139 	{									\
140 	  .pinmux = Z_PINCTRL_PINMUX(group_id, pin_prop, idx),			\
141 IF_ENABLED(DT_PROP(DT_PHANDLE_BY_IDX(group_id, pin_prop, idx), pin_pue),	\
142 	  (.pin_ctrl_flags = Z_PINCTRL_MCUX_IMX_PUE_PUS(group_id),))		\
143 IF_ENABLED(DT_PROP(DT_PHANDLE_BY_IDX(group_id, pin_prop, idx), pin_pdrv),	\
144 	  (.pin_ctrl_flags = Z_PINCTRL_MCUX_IMX_PDRV(group_id),))		\
145 IF_ENABLED(DT_PROP(DT_PHANDLE_BY_IDX(group_id, pin_prop, idx), pin_lpsr),	\
146 	  (.pin_ctrl_flags = Z_PINCTRL_MCUX_IMX_LPSR(group_id),))		\
147 IF_ENABLED(DT_PROP(DT_PHANDLE_BY_IDX(group_id, pin_prop, idx), pin_snvs),	\
148 	  (.pin_ctrl_flags = Z_PINCTRL_MCUX_IMX_SNVS(group_id),))		\
149 	},
150 
151 
152 #define Z_PINCTRL_STATE_PINS_INIT(node_id, prop)			\
153 	{DT_FOREACH_CHILD_VARGS(DT_PHANDLE(node_id, prop),		\
154 		DT_FOREACH_PROP_ELEM, pinmux, Z_PINCTRL_STATE_PIN_INIT)};	\
155 
156 
157 #ifdef __cplusplus
158 }
159 #endif
160 
161 #endif /* ZEPHYR_SOC_ARM_NXP_IMX_RT_PINCTRL_RT11XX_H_ */
162