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