1 /*
2  * Copyright (c) 2022 Nuvoton Technology Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef _NUVOTON_PINCTRL_SOC_H_
8 #define _NUVOTON_PINCTRL_SOC_H_
9 
10 #include <zephyr/devicetree.h>
11 #include <zephyr/sys/util_macro.h>
12 #include <zephyr/types.h>
13 
14 /**
15  * @brief Pinctrl node types in NPCX series
16  */
17 enum npcx_pinctrl_type {
18 	NPCX_PINCTRL_TYPE_PERIPH,
19 	NPCX_PINCTRL_TYPE_DEVICE_CTRL,
20 	NPCX_PINCTRL_TYPE_PSL_IN,
21 	NPCX_PINCTRL_TYPE_RESERVED,
22 };
23 
24 /**
25  * @brief Suppoerted peripheral device configuration type in NPCX series
26  */
27 enum npcx_periph_type {
28 	NPCX_PINCTRL_TYPE_PERIPH_PINMUX,
29 	NPCX_PINCTRL_TYPE_PERIPH_PUPD,
30 	NPCX_PINCTRL_TYPE_PERIPH_DRIVE,
31 };
32 
33 /**
34  * @brief Suppoerted IO bias type in NPCX series
35  */
36 enum npcx_io_bias_type {
37 	NPCX_BIAS_TYPE_NONE,
38 	NPCX_BIAS_TYPE_PULL_DOWN,
39 	NPCX_BIAS_TYPE_PULL_UP,
40 };
41 
42 /**
43  * @brief Suppoerted IO drive type in NPCX series
44  */
45 enum npcx_io_drive_type {
46 	NPCX_DRIVE_TYPE_PUSH_PULL,
47 	NPCX_DRIVE_TYPE_OPEN_DRAIN,
48 };
49 
50 /**
51  * @brief Suppoerted PSL input detection mode in NPCX series
52  */
53 enum npcx_psl_in_mode {
54 	NPCX_PSL_IN_MODE_LEVEL,
55 	NPCX_PSL_IN_MODE_EDGE,
56 };
57 
58 /**
59  * @brief Suppoerted PSL input detection polarity in NPCX series
60  */
61 enum npcx_psl_in_pol {
62 	NPCX_PSL_IN_POL_LOW,
63 	NPCX_PSL_IN_POL_HIGH,
64 };
65 
66 /**
67  * @brief NPCX peripheral device configuration structure
68  *
69  * Used to indicate the peripheral device's corresponding register/bit for
70  * pin-muxing, pull-up/down and so on.
71  */
72 struct npcx_periph {
73 	/** Related register group for peripheral device. */
74 	uint16_t group: 8;
75 	/** Related register bit for peripheral device. */
76 	uint16_t bit: 3;
77 	/** The polarity for peripheral device functionality. */
78 	bool inverted: 1;
79 	/** The type of peripheral device configuration. */
80 	enum npcx_periph_type type: 2;
81 	/** Reserved field. */
82 	uint16_t reserved: 2;
83 } __packed;
84 
85 /**
86  * @brief NPCX device control structure
87  *
88  * Used to indicate the device's corresponding register/field for its io
89  * characteristics such as tri-state, power supply type selection, and so on.
90  */
91 struct npcx_dev_ctl {
92 	/** Related register offset for device configuration. */
93 	uint16_t offest: 5;
94 	/** Related register field offset for device control. */
95 	uint16_t field_offset: 3;
96 	/** Related register field size for device control. */
97 	uint16_t field_size: 3;
98 	/** field value */
99 	uint16_t field_value: 5;
100 } __packed;
101 
102 /**
103  * @brief NPCX Power Switch Logic (PSL) input pad configuration structure
104  *
105  * Used to indicate a Power Switch Logic (PSL) input detection configuration
106  * such as detection polarity, port number, and so on.
107  */
108 struct npcx_psl_input {
109 	/** Indicate a PSL input port number. */
110 	uint16_t port: 5;
111 	/** Related register group for detection polarity of PSL input. */
112 	uint16_t pol_group: 8;
113 	/** Related register bit for detection polarity of PSL input. */
114 	uint16_t pol_bit: 3;
115 } __packed;
116 
117 /**
118  * @brief Type for NPCX pin configuration. Please make sure the size of this
119  *        structure is 4 bytes in case the impact of ROM usage.
120  */
121 struct npcx_pinctrl {
122 	union {
123 		struct npcx_periph periph;
124 		struct npcx_dev_ctl dev_ctl;
125 		struct npcx_psl_input psl_in;
126 		uint16_t cfg_word;
127 	} cfg;
128 	struct {
129 		/** Indicates the current pinctrl type. */
130 		enum npcx_pinctrl_type type :2;
131 		/** Properties used for pinmuxing. */
132 		bool pinmux_lock :1;
133 		bool pinmux_gpio :1;
134 		/** Properties used for io-pad. */
135 		enum npcx_io_bias_type io_bias_type :2;
136 		enum npcx_io_drive_type io_drive_type :1;
137 		/** Properties used for PSL input. */
138 		enum npcx_psl_in_mode psl_in_mode :1;
139 		enum npcx_psl_in_pol psl_in_polarity :1;
140 		uint16_t reserved :7;
141 	} flags;
142 } __packed;
143 
144 typedef struct npcx_pinctrl pinctrl_soc_pin_t;
145 
146 /** Helper macros for NPCX pinctrl configurations. */
147 #define  Z_PINCTRL_NPCX_BIAS_TYPE(node_id)					\
148 	COND_CODE_1(DT_PROP(node_id, bias_pull_up), (NPCX_BIAS_TYPE_PULL_UP),	\
149 		(COND_CODE_1(DT_PROP(node_id, bias_pull_down),			\
150 		(NPCX_BIAS_TYPE_PULL_DOWN), (NPCX_BIAS_TYPE_NONE))))
151 
152 #define  Z_PINCTRL_NPCX_DRIVE_TYPE(node_id)					\
153 	COND_CODE_1(DT_PROP(node_id, drive_open_drain),				\
154 		(NPCX_DRIVE_TYPE_OPEN_DRAIN), (NPCX_DRIVE_TYPE_PUSH_PULL))
155 
156 #define Z_PINCTRL_NPCX_HAS_PUPD_PROP(node_id)		\
157 	UTIL_OR(DT_PROP(node_id, bias_pull_down),	\
158 		DT_PROP(node_id, bias_pull_up))
159 
160 #define Z_PINCTRL_NPCX_HAS_DRIVE_PROP(node_id, node_periph)	\
161 	UTIL_AND(DT_PROP(node_id, drive_open_drain),		\
162 		DT_NODE_HAS_PROP(node_periph, pwm_channel))
163 
164 #define Z_PINCTRL_NPCX_HAS_PSL_IN_PROP(node_id)			\
165 	UTIL_AND(DT_NODE_HAS_PROP(node_id, psl_in_pol),		\
166 		DT_NODE_HAS_PROP(node_id, psl_in_mode))
167 
168 /**
169  * @brief Utility macro to initialize a periphral pinmux configuration.
170  *
171  * @param node_id Node identifier.
172  * @param prop Property name for pinmux configuration. (i.e. 'pinmux')
173  */
174 #define Z_PINCTRL_NPCX_PERIPH_PINMUX_INIT(node_id, prop)				\
175 	{										\
176 		.flags.type = NPCX_PINCTRL_TYPE_PERIPH,					\
177 		.flags.pinmux_lock = DT_PROP(node_id, pinmux_locked),			\
178 		.flags.pinmux_gpio = DT_PROP(node_id, pinmux_gpio),			\
179 		.cfg.periph.type = NPCX_PINCTRL_TYPE_PERIPH_PINMUX,			\
180 		.cfg.periph.group = DT_PHA(DT_PROP(node_id, prop), alts, group),	\
181 		.cfg.periph.bit = DT_PHA(DT_PROP(node_id, prop), alts, bit),		\
182 		.cfg.periph.inverted = DT_PHA(DT_PROP(node_id, prop), alts, inv),	\
183 	},
184 
185 /**
186  * @brief Utility macro to initialize a periphral pinmux configuration.
187  *
188  * @param node_id Node identifier.
189  * @param prop Property name for pinmux configuration. (i.e. 'pinmux')
190  */
191 #define Z_PINCTRL_NPCX_DEVICE_CONTROL_INIT(node_id, prop)			\
192 	{									\
193 		.flags.type = NPCX_PINCTRL_TYPE_DEVICE_CTRL,			\
194 		.cfg.dev_ctl.offest = DT_PROP_BY_IDX(node_id, prop, 0),		\
195 		.cfg.dev_ctl.field_offset = DT_PROP_BY_IDX(node_id, prop, 1),	\
196 		.cfg.dev_ctl.field_size = DT_PROP_BY_IDX(node_id, prop, 2),	\
197 		.cfg.dev_ctl.field_value = DT_PROP_BY_IDX(node_id, prop, 3),	\
198 	},
199 
200 /**
201  * @brief Utility macro to initialize a periphral pull-up/down configuration.
202  *
203  * @param node_id Node identifier.
204  * @param prop Property name for pull-up/down configuration. (i.e. 'periph-pupd')
205  */
206 #define Z_PINCTRL_NPCX_PERIPH_PUPD_INIT(node_id, prop)				\
207 	{									\
208 		.flags.type = NPCX_PINCTRL_TYPE_PERIPH,				\
209 		.flags.io_bias_type = Z_PINCTRL_NPCX_BIAS_TYPE(node_id),	\
210 		.cfg.periph.type = NPCX_PINCTRL_TYPE_PERIPH_PUPD,		\
211 		.cfg.periph.group = DT_PROP_BY_IDX(node_id, prop,  0),		\
212 		.cfg.periph.bit = DT_PROP_BY_IDX(node_id, prop,  1),		\
213 	},
214 
215 /**
216  * @brief Utility macro to initialize a periphral drive mode configuration.
217  *
218  * @param node_id Node identifier.
219  * @param node_periph Peripheral node identifier.
220  */
221 #define Z_PINCTRL_NPCX_PERIPH_DRIVE_INIT(node_id, node_periph)			\
222 	{									\
223 		.flags.type = NPCX_PINCTRL_TYPE_PERIPH,				\
224 		.flags.io_drive_type = Z_PINCTRL_NPCX_DRIVE_TYPE(node_id),	\
225 		.cfg.periph.type = NPCX_PINCTRL_TYPE_PERIPH_DRIVE,		\
226 		.cfg.periph.group = DT_PROP(node_periph, pwm_channel),		\
227 	},
228 
229 /*
230  * @brief Utility macro to initialize a Power Switch Logic (PSL) input detection
231  *        configurations.
232  *
233  * @param node_id Node identifier.
234  * @param prop Property name for pull-up/down configuration. (i.e. 'polarity')
235  */
236 #define Z_PINCTRL_NPCX_PSL_IN_DETECT_CONF_INIT(node_id, prop)				\
237 	{										\
238 		.flags.type = NPCX_PINCTRL_TYPE_PSL_IN,					\
239 		.flags.psl_in_mode = DT_ENUM_IDX(node_id, psl_in_mode),			\
240 		.flags.psl_in_polarity = DT_ENUM_IDX(node_id, psl_in_pol),		\
241 		.cfg.psl_in.port = DT_PROP(node_id, psl_offset),			\
242 		.cfg.psl_in.pol_group = DT_PHA(DT_PROP(node_id, prop), alts, group),	\
243 		.cfg.psl_in.pol_bit = DT_PHA(DT_PROP(node_id, prop), alts, bit),	\
244 	},
245 
246 /**
247  * @brief Utility macro to initialize all peripheral confiurations for each pin.
248  *
249  * @param node_id Node identifier.
250  * @param prop Pinctrl state property name. (i.e. 'pinctrl-0/1/2')
251  * @param idx Property entry index.
252  */
253 #define Z_PINCTRL_STATE_PIN_INIT(node_id, prop, idx)					\
254 	COND_CODE_1(Z_PINCTRL_NPCX_HAS_DRIVE_PROP(					\
255 			DT_PROP_BY_IDX(node_id, prop, idx), node_id),			\
256 		(Z_PINCTRL_NPCX_PERIPH_DRIVE_INIT(					\
257 			DT_PROP_BY_IDX(node_id, prop, idx), node_id)), ())		\
258 	COND_CODE_1(Z_PINCTRL_NPCX_HAS_PUPD_PROP(DT_PROP_BY_IDX(node_id, prop, idx)),	\
259 		(Z_PINCTRL_NPCX_PERIPH_PUPD_INIT(					\
260 			DT_PROP_BY_IDX(node_id, prop, idx), periph_pupd)), ())		\
261 	COND_CODE_1(Z_PINCTRL_NPCX_HAS_PSL_IN_PROP(DT_PROP_BY_IDX(node_id, prop, idx)),	\
262 		(Z_PINCTRL_NPCX_PSL_IN_DETECT_CONF_INIT(				\
263 			DT_PROP_BY_IDX(node_id, prop, idx), psl_polarity)), ())		\
264 	COND_CODE_1(DT_NODE_HAS_PROP(DT_PROP_BY_IDX(node_id, prop, idx), dev_ctl),	\
265 		(Z_PINCTRL_NPCX_DEVICE_CONTROL_INIT(					\
266 			DT_PROP_BY_IDX(node_id, prop, idx), dev_ctl)), ())		\
267 	COND_CODE_1(DT_NODE_HAS_PROP(DT_PROP_BY_IDX(node_id, prop, idx), pinmux),	\
268 		(Z_PINCTRL_NPCX_PERIPH_PINMUX_INIT(					\
269 			DT_PROP_BY_IDX(node_id, prop, idx), pinmux)), ())
270 
271 /**
272  * @brief Utility macro to initialize state pins contained in a given property.
273  *
274  * @param node_id Node identifier.
275  * @param prop Property name describing state pins.
276  */
277 #define Z_PINCTRL_STATE_PINS_INIT(node_id, prop)	\
278 	{DT_FOREACH_PROP_ELEM(node_id, prop, Z_PINCTRL_STATE_PIN_INIT)}
279 
280 #endif /* _NUVOTON_PINCTRL_SOC_H_ */
281