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