1 /*
2  * Copyright (c) 2022 ITE Corporation. All Rights Reserved
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT ite_it8xxx2_wuc
8 
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/interrupt_controller/wuc_ite_it8xxx2.h>
11 #include <zephyr/dt-bindings/interrupt-controller/it8xxx2-wuc.h>
12 #include <zephyr/kernel.h>
13 #include <soc.h>
14 #include <soc_common.h>
15 #include <stdlib.h>
16 
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(wuc_ite_it8xxx2, CONFIG_INTC_LOG_LEVEL);
19 
20 /* Driver config */
21 struct it8xxx2_wuc_cfg {
22 	/* WUC wakeup edge mode register */
23 	uint8_t *reg_wuemr;
24 	/* WUC wakeup edge sense register */
25 	uint8_t *reg_wuesr;
26 	/* WUC wakeup enable register */
27 	uint8_t *reg_wuenr;
28 	/* WUC wakeup both edge mode register */
29 	uint8_t *reg_wubemr;
30 };
31 
it8xxx2_wuc_enable(const struct device * dev,uint8_t mask)32 void it8xxx2_wuc_enable(const struct device *dev, uint8_t mask)
33 {
34 	const struct it8xxx2_wuc_cfg *config = dev->config;
35 	volatile uint8_t *reg_wuenr = config->reg_wuenr;
36 
37 	/*
38 	 * WUC group only 1, 3, and 4 have enable/disable register,
39 	 * others are always enabled.
40 	 */
41 	if (reg_wuenr == IT8XXX2_WUC_UNUSED_REG) {
42 		return;
43 	}
44 
45 	/* Enable wakeup interrupt of the pin */
46 	*reg_wuenr |= mask;
47 }
48 
it8xxx2_wuc_disable(const struct device * dev,uint8_t mask)49 void it8xxx2_wuc_disable(const struct device *dev, uint8_t mask)
50 {
51 	const struct it8xxx2_wuc_cfg *config = dev->config;
52 	volatile uint8_t *reg_wuenr = config->reg_wuenr;
53 
54 	/*
55 	 * WUC group only 1, 3, and 4 have enable/disable register,
56 	 * others are always enabled.
57 	 */
58 	if (reg_wuenr == IT8XXX2_WUC_UNUSED_REG) {
59 		return;
60 	}
61 
62 	/* Disable wakeup interrupt of the pin */
63 	*reg_wuenr &= ~mask;
64 }
65 
it8xxx2_wuc_clear_status(const struct device * dev,uint8_t mask)66 void it8xxx2_wuc_clear_status(const struct device *dev, uint8_t mask)
67 {
68 	const struct it8xxx2_wuc_cfg *config = dev->config;
69 	volatile uint8_t *reg_wuesr = config->reg_wuesr;
70 
71 	if (reg_wuesr == IT8XXX2_WUC_UNUSED_REG) {
72 		return;
73 	}
74 
75 	/* W/C wakeup interrupt status of the pin */
76 	*reg_wuesr = mask;
77 }
78 
it8xxx2_wuc_set_polarity(const struct device * dev,uint8_t mask,uint32_t flags)79 void it8xxx2_wuc_set_polarity(const struct device *dev, uint8_t mask, uint32_t flags)
80 {
81 	const struct it8xxx2_wuc_cfg *config = dev->config;
82 	volatile uint8_t *reg_wuemr = config->reg_wuemr;
83 	volatile uint8_t *reg_wubemr = config->reg_wubemr;
84 
85 	if (reg_wuemr == IT8XXX2_WUC_UNUSED_REG) {
86 		return;
87 	}
88 
89 	/* Set wakeup interrupt edge trigger mode of the pin */
90 	if ((flags & WUC_TYPE_EDGE_BOTH) == WUC_TYPE_EDGE_RISING) {
91 		*reg_wubemr &= ~mask;
92 		*reg_wuemr &= ~mask;
93 	} else if ((flags & WUC_TYPE_EDGE_BOTH) == WUC_TYPE_EDGE_FALLING) {
94 		*reg_wubemr &= ~mask;
95 		*reg_wuemr |= mask;
96 	} else {
97 		/* Both edge trigger mode */
98 		*reg_wubemr |= mask;
99 	}
100 }
101 
102 #define IT8XXX2_WUC_INIT(inst)						       \
103 									       \
104 	static const struct it8xxx2_wuc_cfg it8xxx2_wuc_cfg_##inst = {	       \
105 		.reg_wuemr = (uint8_t *) DT_INST_REG_ADDR_BY_IDX(inst, 0),     \
106 		.reg_wuesr = (uint8_t *) DT_INST_REG_ADDR_BY_IDX(inst, 1),     \
107 		.reg_wuenr = (uint8_t *) DT_INST_REG_ADDR_BY_IDX(inst, 2),     \
108 		.reg_wubemr = (uint8_t *) DT_INST_REG_ADDR_BY_IDX(inst, 3),    \
109 	};								       \
110 									       \
111 	DEVICE_DT_INST_DEFINE(inst,					       \
112 			      NULL,					       \
113 			      NULL,					       \
114 			      NULL,					       \
115 			      &it8xxx2_wuc_cfg_##inst,			       \
116 			      PRE_KERNEL_1,				       \
117 			      CONFIG_KERNEL_INIT_PRIORITY_OBJECTS,	       \
118 			      NULL);
119 
120 DT_INST_FOREACH_STATUS_OKAY(IT8XXX2_WUC_INIT)
121