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