1 /*
2 * Copyright (c) 2023 ITE Corporation. All Rights Reserved.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 */
7
8 #define DT_DRV_COMPAT ite_it8xxx2_gpio_v2
9
10 #include <errno.h>
11 #include <soc.h>
12 #include <soc_dt.h>
13 #include <string.h>
14 #include <zephyr/device.h>
15 #include <zephyr/drivers/gpio.h>
16 #include <zephyr/drivers/gpio/gpio_utils.h>
17 #include <zephyr/dt-bindings/gpio/ite-it8xxx2-gpio.h>
18 #include <zephyr/dt-bindings/interrupt-controller/ite-intc.h>
19 #include <zephyr/irq.h>
20 #include <zephyr/sys/util.h>
21 #include <zephyr/types.h>
22 #include <zephyr/logging/log.h>
23 LOG_MODULE_REGISTER(gpio_it8xxx2, LOG_LEVEL_ERR);
24
25 /*
26 * Structure gpio_ite_cfg is about the setting of GPIO
27 * this config will be used at initial time
28 */
29 struct gpio_ite_cfg {
30 /* gpio_driver_config needs to be first */
31 struct gpio_driver_config common;
32 /* GPIO port data register (bit mapping to pin) */
33 uintptr_t reg_gpdr;
34 /* GPIO port data mirror register (bit mapping to pin) */
35 uintptr_t reg_gpdmr;
36 /* GPIO port output type register (bit mapping to pin) */
37 uintptr_t reg_gpotr;
38 /* GPIO port 1.8V select register (bit mapping to pin) */
39 uintptr_t reg_p18scr;
40 /* GPIO port control register (byte mapping to pin) */
41 uintptr_t reg_gpcr;
42 /* Wake up control base register */
43 uintptr_t wuc_base[8];
44 /* Wake up control mask */
45 uint8_t wuc_mask[8];
46 /* GPIO's irq */
47 uint8_t gpio_irq[8];
48 /* Support input voltage selection */
49 uint8_t has_volt_sel[8];
50 /* Number of pins per group of GPIO */
51 uint8_t num_pins;
52 };
53
54 /* Structure gpio_ite_data is about callback function */
55 struct gpio_ite_data {
56 struct gpio_driver_data common;
57 sys_slist_t callbacks;
58 uint8_t volt_default_set;
59 };
60
61 /**
62 * Driver functions
63 */
gpio_ite_configure(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)64 static int gpio_ite_configure(const struct device *dev,
65 gpio_pin_t pin,
66 gpio_flags_t flags)
67 {
68 const struct gpio_ite_cfg *gpio_config = dev->config;
69 volatile uint8_t *reg_gpdr = (uint8_t *)gpio_config->reg_gpdr;
70 volatile uint8_t *reg_gpotr = (uint8_t *)gpio_config->reg_gpotr;
71 volatile uint8_t *reg_p18scr = (uint8_t *)gpio_config->reg_p18scr;
72 volatile uint8_t *reg_gpcr = (uint8_t *)gpio_config->reg_gpcr + pin;
73 struct gpio_ite_data *data = dev->data;
74 uint8_t mask = BIT(pin);
75
76 /* Don't support "open source" mode */
77 if (((flags & GPIO_SINGLE_ENDED) != 0) &&
78 ((flags & GPIO_LINE_OPEN_DRAIN) == 0)) {
79 return -ENOTSUP;
80 }
81
82 if (flags == GPIO_DISCONNECTED) {
83 *reg_gpcr = GPCR_PORT_PIN_MODE_TRISTATE;
84 /*
85 * Since not all GPIOs can be to configured as tri-state,
86 * prompt error if pin doesn't support the flag.
87 */
88 if (*reg_gpcr != GPCR_PORT_PIN_MODE_TRISTATE) {
89 /* Go back to default setting (input) */
90 *reg_gpcr = GPCR_PORT_PIN_MODE_INPUT;
91 LOG_ERR("Cannot config the node-gpio@%x, pin=%d as tri-state",
92 (uint32_t)reg_gpdr, pin);
93 return -ENOTSUP;
94 }
95 /*
96 * The following configuration isn't necessary because the pin
97 * was configured as disconnected.
98 */
99 return 0;
100 }
101
102 /*
103 * Select open drain first, so that we don't glitch the signal
104 * when changing the line to an output.
105 */
106 if (flags & GPIO_OPEN_DRAIN) {
107 *reg_gpotr |= mask;
108 } else {
109 *reg_gpotr &= ~mask;
110 }
111
112 /* 1.8V or 3.3V */
113 if (gpio_config->has_volt_sel[pin]) {
114 gpio_flags_t volt = flags & IT8XXX2_GPIO_VOLTAGE_MASK;
115
116 if (volt == IT8XXX2_GPIO_VOLTAGE_1P8) {
117 __ASSERT(!(flags & GPIO_PULL_UP),
118 "Don't enable internal pullup if 1.8V voltage is used");
119 *reg_p18scr |= mask;
120 data->volt_default_set &= ~mask;
121 } else if (volt == IT8XXX2_GPIO_VOLTAGE_3P3) {
122 *reg_p18scr &= ~mask;
123 /*
124 * A variable is needed to store the difference between
125 * 3.3V and default so that the flag can be distinguished
126 * between the two in gpio_ite_get_config.
127 */
128 data->volt_default_set &= ~mask;
129 } else if (volt == IT8XXX2_GPIO_VOLTAGE_DEFAULT) {
130 *reg_p18scr &= ~mask;
131 data->volt_default_set |= mask;
132 } else {
133 return -EINVAL;
134 }
135 }
136
137 /* If output, set level before changing type to an output. */
138 if (flags & GPIO_OUTPUT) {
139 if (flags & GPIO_OUTPUT_INIT_HIGH) {
140 *reg_gpdr |= mask;
141 } else if (flags & GPIO_OUTPUT_INIT_LOW) {
142 *reg_gpdr &= ~mask;
143 }
144 }
145
146 /* Set input or output. */
147 if (flags & GPIO_OUTPUT) {
148 *reg_gpcr = (*reg_gpcr | GPCR_PORT_PIN_MODE_OUTPUT) &
149 ~GPCR_PORT_PIN_MODE_INPUT;
150 } else {
151 *reg_gpcr = (*reg_gpcr | GPCR_PORT_PIN_MODE_INPUT) &
152 ~GPCR_PORT_PIN_MODE_OUTPUT;
153 }
154
155 /* Handle pullup / pulldown */
156 if (flags & GPIO_PULL_UP) {
157 *reg_gpcr = (*reg_gpcr | GPCR_PORT_PIN_MODE_PULLUP) &
158 ~GPCR_PORT_PIN_MODE_PULLDOWN;
159 } else if (flags & GPIO_PULL_DOWN) {
160 *reg_gpcr = (*reg_gpcr | GPCR_PORT_PIN_MODE_PULLDOWN) &
161 ~GPCR_PORT_PIN_MODE_PULLUP;
162 } else {
163 /* No pull up/down */
164 *reg_gpcr &= ~(GPCR_PORT_PIN_MODE_PULLUP |
165 GPCR_PORT_PIN_MODE_PULLDOWN);
166 }
167
168 return 0;
169 }
170
171 #ifdef CONFIG_GPIO_GET_CONFIG
gpio_ite_get_config(const struct device * dev,gpio_pin_t pin,gpio_flags_t * out_flags)172 static int gpio_ite_get_config(const struct device *dev,
173 gpio_pin_t pin,
174 gpio_flags_t *out_flags)
175 {
176 const struct gpio_ite_cfg *gpio_config = dev->config;
177 volatile uint8_t *reg_gpdr = (uint8_t *)gpio_config->reg_gpdr;
178 volatile uint8_t *reg_gpotr = (uint8_t *)gpio_config->reg_gpotr;
179 volatile uint8_t *reg_p18scr = (uint8_t *)gpio_config->reg_p18scr;
180 volatile uint8_t *reg_gpcr = (uint8_t *)gpio_config->reg_gpcr + pin;
181 struct gpio_ite_data *data = dev->data;
182 uint8_t mask = BIT(pin);
183 gpio_flags_t flags = 0;
184
185 /* push-pull or open-drain */
186 if (*reg_gpotr & mask) {
187 flags |= GPIO_OPEN_DRAIN;
188 }
189
190 /* 1.8V or 3.3V */
191 if (gpio_config->has_volt_sel[pin]) {
192 if (data->volt_default_set & mask) {
193 flags |= IT8XXX2_GPIO_VOLTAGE_DEFAULT;
194 } else {
195 if (*reg_p18scr & mask) {
196 flags |= IT8XXX2_GPIO_VOLTAGE_1P8;
197 } else {
198 flags |= IT8XXX2_GPIO_VOLTAGE_3P3;
199 }
200 }
201 }
202
203 /* set input or output. */
204 if (*reg_gpcr & GPCR_PORT_PIN_MODE_OUTPUT) {
205 flags |= GPIO_OUTPUT;
206
207 /* set level */
208 if (*reg_gpdr & mask) {
209 flags |= GPIO_OUTPUT_HIGH;
210 } else {
211 flags |= GPIO_OUTPUT_LOW;
212 }
213 }
214
215 if (*reg_gpcr & GPCR_PORT_PIN_MODE_INPUT) {
216 flags |= GPIO_INPUT;
217
218 /* pullup / pulldown */
219 if (*reg_gpcr & GPCR_PORT_PIN_MODE_PULLUP) {
220 flags |= GPIO_PULL_UP;
221 }
222
223 if (*reg_gpcr & GPCR_PORT_PIN_MODE_PULLDOWN) {
224 flags |= GPIO_PULL_DOWN;
225 }
226 }
227
228 *out_flags = flags;
229
230 return 0;
231 }
232 #endif
233
gpio_ite_port_get_raw(const struct device * dev,gpio_port_value_t * value)234 static int gpio_ite_port_get_raw(const struct device *dev,
235 gpio_port_value_t *value)
236 {
237 const struct gpio_ite_cfg *gpio_config = dev->config;
238 volatile uint8_t *reg_gpdmr = (uint8_t *)gpio_config->reg_gpdmr;
239
240 /* Get raw bits of GPIO mirror register */
241 *value = *reg_gpdmr;
242
243 return 0;
244 }
245
gpio_ite_port_set_masked_raw(const struct device * dev,gpio_port_pins_t mask,gpio_port_value_t value)246 static int gpio_ite_port_set_masked_raw(const struct device *dev,
247 gpio_port_pins_t mask,
248 gpio_port_value_t value)
249 {
250 const struct gpio_ite_cfg *gpio_config = dev->config;
251 volatile uint8_t *reg_gpdr = (uint8_t *)gpio_config->reg_gpdr;
252 uint8_t out = *reg_gpdr;
253
254 *reg_gpdr = ((out & ~mask) | (value & mask));
255
256 return 0;
257 }
258
gpio_ite_port_set_bits_raw(const struct device * dev,gpio_port_pins_t pins)259 static int gpio_ite_port_set_bits_raw(const struct device *dev,
260 gpio_port_pins_t pins)
261 {
262 const struct gpio_ite_cfg *gpio_config = dev->config;
263 volatile uint8_t *reg_gpdr = (uint8_t *)gpio_config->reg_gpdr;
264
265 /* Set raw bits of GPIO data register */
266 *reg_gpdr |= pins;
267
268 return 0;
269 }
270
gpio_ite_port_clear_bits_raw(const struct device * dev,gpio_port_pins_t pins)271 static int gpio_ite_port_clear_bits_raw(const struct device *dev,
272 gpio_port_pins_t pins)
273 {
274 const struct gpio_ite_cfg *gpio_config = dev->config;
275 volatile uint8_t *reg_gpdr = (uint8_t *)gpio_config->reg_gpdr;
276
277 /* Clear raw bits of GPIO data register */
278 *reg_gpdr &= ~pins;
279
280 return 0;
281 }
282
gpio_ite_port_toggle_bits(const struct device * dev,gpio_port_pins_t pins)283 static int gpio_ite_port_toggle_bits(const struct device *dev,
284 gpio_port_pins_t pins)
285 {
286 const struct gpio_ite_cfg *gpio_config = dev->config;
287 volatile uint8_t *reg_gpdr = (uint8_t *)gpio_config->reg_gpdr;
288
289 /* Toggle raw bits of GPIO data register */
290 *reg_gpdr ^= pins;
291
292 return 0;
293 }
294
gpio_ite_manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)295 static int gpio_ite_manage_callback(const struct device *dev,
296 struct gpio_callback *callback,
297 bool set)
298 {
299 struct gpio_ite_data *data = dev->data;
300
301 return gpio_manage_callback(&data->callbacks, callback, set);
302 }
303
gpio_ite_isr(const void * arg)304 static void gpio_ite_isr(const void *arg)
305 {
306 const struct device *dev = arg;
307 const struct gpio_ite_cfg *gpio_config = dev->config;
308 struct gpio_ite_data *data = dev->data;
309 uint8_t irq = ite_intc_get_irq_num();
310 uint8_t num_pins = gpio_config->num_pins;
311 uint8_t pin;
312
313 for (pin = 0; pin <= num_pins; pin++) {
314 if (irq == gpio_config->gpio_irq[pin]) {
315 volatile uint8_t *reg_base =
316 (uint8_t *)gpio_config->wuc_base[pin];
317 volatile uint8_t *reg_wuesr = reg_base + 1;
318 uint8_t wuc_mask = gpio_config->wuc_mask[pin];
319
320 /* Clear the WUC status register. */
321 *reg_wuesr = wuc_mask;
322 gpio_fire_callbacks(&data->callbacks, dev, BIT(pin));
323
324 break;
325 }
326 }
327 }
328
gpio_ite_pin_interrupt_configure(const struct device * dev,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)329 static int gpio_ite_pin_interrupt_configure(const struct device *dev,
330 gpio_pin_t pin,
331 enum gpio_int_mode mode,
332 enum gpio_int_trig trig)
333 {
334 const struct gpio_ite_cfg *gpio_config = dev->config;
335 uint8_t gpio_irq = gpio_config->gpio_irq[pin];
336
337 #ifdef CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT
338 if (mode == GPIO_INT_MODE_DISABLED || mode == GPIO_INT_MODE_DISABLE_ONLY) {
339 #else
340 if (mode == GPIO_INT_MODE_DISABLED) {
341 #endif /* CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT */
342 /* Disable GPIO interrupt */
343 irq_disable(gpio_irq);
344 return 0;
345 #ifdef CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT
346 } else if (mode == GPIO_INT_MODE_ENABLE_ONLY) {
347 /* Only enable GPIO interrupt */
348 irq_enable(gpio_irq);
349 return 0;
350 #endif /* CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT */
351 }
352
353 if (mode == GPIO_INT_MODE_LEVEL) {
354 LOG_ERR("Level trigger mode not supported");
355 return -ENOTSUP;
356 }
357
358 /* Disable irq before configuring it */
359 irq_disable(gpio_irq);
360
361 if (trig & GPIO_INT_TRIG_BOTH) {
362 volatile uint8_t *reg_base = (uint8_t *)gpio_config->wuc_base[pin];
363 volatile uint8_t *reg_wuemr = reg_base;
364 volatile uint8_t *reg_wuesr = reg_base + 1;
365 volatile uint8_t *reg_wubemr = reg_base + 3;
366 uint8_t wuc_mask = gpio_config->wuc_mask[pin];
367
368 /* Set both edges interrupt. */
369 if ((trig & GPIO_INT_TRIG_BOTH) == GPIO_INT_TRIG_BOTH) {
370 *reg_wubemr |= wuc_mask;
371 } else {
372 *reg_wubemr &= ~wuc_mask;
373 }
374
375 if (trig & GPIO_INT_TRIG_LOW) {
376 *reg_wuemr |= wuc_mask;
377 } else {
378 *reg_wuemr &= ~wuc_mask;
379 }
380 /*
381 * Always write 1 to clear the WUC status register after
382 * modifying edge mode selection register (WUBEMR and WUEMR).
383 */
384 *reg_wuesr = wuc_mask;
385 }
386
387 /* Enable GPIO interrupt */
388 irq_connect_dynamic(gpio_irq, 0, gpio_ite_isr, dev, 0);
389 irq_enable(gpio_irq);
390
391 return 0;
392 }
393
394 static const struct gpio_driver_api gpio_ite_driver_api = {
395 .pin_configure = gpio_ite_configure,
396 #ifdef CONFIG_GPIO_GET_CONFIG
397 .pin_get_config = gpio_ite_get_config,
398 #endif
399 .port_get_raw = gpio_ite_port_get_raw,
400 .port_set_masked_raw = gpio_ite_port_set_masked_raw,
401 .port_set_bits_raw = gpio_ite_port_set_bits_raw,
402 .port_clear_bits_raw = gpio_ite_port_clear_bits_raw,
403 .port_toggle_bits = gpio_ite_port_toggle_bits,
404 .pin_interrupt_configure = gpio_ite_pin_interrupt_configure,
405 .manage_callback = gpio_ite_manage_callback,
406 };
407
408 static int gpio_ite_init(const struct device *dev)
409 {
410 return 0;
411 }
412
413 #define GPIO_ITE_DEV_CFG_DATA(inst) \
414 static struct gpio_ite_data gpio_ite_data_##inst; \
415 static const struct gpio_ite_cfg gpio_ite_cfg_##inst = { \
416 .common = { \
417 .port_pin_mask = \
418 GPIO_PORT_PIN_MASK_FROM_DT_INST(inst) \
419 }, \
420 .reg_gpdr = DT_INST_REG_ADDR_BY_IDX(inst, 0), \
421 .reg_gpdmr = DT_INST_REG_ADDR_BY_IDX(inst, 1), \
422 .reg_gpotr = DT_INST_REG_ADDR_BY_IDX(inst, 2), \
423 .reg_p18scr = DT_INST_REG_ADDR_BY_IDX(inst, 3), \
424 .reg_gpcr = DT_INST_REG_ADDR_BY_IDX(inst, 4), \
425 .wuc_base = DT_INST_PROP_OR(inst, wuc_base, {0}), \
426 .wuc_mask = DT_INST_PROP_OR(inst, wuc_mask, {0}), \
427 .gpio_irq = IT8XXX2_DT_GPIO_IRQ_LIST(inst), \
428 .has_volt_sel = DT_INST_PROP_OR(inst, has_volt_sel, {0}), \
429 .num_pins = DT_INST_PROP(inst, ngpios), \
430 }; \
431 DEVICE_DT_INST_DEFINE(inst, \
432 gpio_ite_init, \
433 NULL, \
434 &gpio_ite_data_##inst, \
435 &gpio_ite_cfg_##inst, \
436 PRE_KERNEL_1, \
437 CONFIG_GPIO_INIT_PRIORITY, \
438 &gpio_ite_driver_api);
439
440 DT_INST_FOREACH_STATUS_OKAY(GPIO_ITE_DEV_CFG_DATA)
441
442 static int gpio_it8xxx2_init_set(void)
443 {
444 if (IS_ENABLED(CONFIG_SOC_IT8XXX2_GPIO_GROUP_K_L_DEFAULT_PULL_DOWN)) {
445 const struct device *const gpiok = DEVICE_DT_GET(DT_NODELABEL(gpiok));
446 const struct device *const gpiol = DEVICE_DT_GET(DT_NODELABEL(gpiol));
447
448 for (int i = 0; i < 8; i++) {
449 gpio_pin_configure(gpiok, i, GPIO_INPUT | GPIO_PULL_DOWN);
450 gpio_pin_configure(gpiol, i, GPIO_INPUT | GPIO_PULL_DOWN);
451 }
452 }
453
454 return 0;
455 }
456 SYS_INIT(gpio_it8xxx2_init_set, PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY);
457