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