| /* |
| * Copyright (c) 2022 ITE Corporation. All Rights Reserved |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #define DT_DRV_COMPAT ite_it8xxx2_wuc |
| |
| #include <zephyr/device.h> |
| #include <zephyr/drivers/interrupt_controller/wuc_ite_it8xxx2.h> |
| #include <zephyr/dt-bindings/interrupt-controller/it8xxx2-wuc.h> |
| #include <zephyr/kernel.h> |
| #include <soc.h> |
| #include <soc_common.h> |
| #include <stdlib.h> |
| |
| #include <zephyr/logging/log.h> |
| LOG_MODULE_REGISTER(wuc_ite_it8xxx2, CONFIG_INTC_LOG_LEVEL); |
| |
| /* Driver config */ |
| struct it8xxx2_wuc_cfg { |
| /* WUC wakeup edge mode register */ |
| uint8_t *reg_wuemr; |
| /* WUC wakeup edge sense register */ |
| uint8_t *reg_wuesr; |
| /* WUC wakeup enable register */ |
| uint8_t *reg_wuenr; |
| /* WUC wakeup both edge mode register */ |
| uint8_t *reg_wubemr; |
| }; |
| |
| void it8xxx2_wuc_enable(const struct device *dev, uint8_t mask) |
| { |
| const struct it8xxx2_wuc_cfg *config = dev->config; |
| volatile uint8_t *reg_wuenr = config->reg_wuenr; |
| |
| /* |
| * WUC group only 1, 3, and 4 have enable/disable register, |
| * others are always enabled. |
| */ |
| if (reg_wuenr == IT8XXX2_WUC_UNUSED_REG) { |
| return; |
| } |
| |
| /* Enable wakeup interrupt of the pin */ |
| *reg_wuenr |= mask; |
| } |
| |
| void it8xxx2_wuc_disable(const struct device *dev, uint8_t mask) |
| { |
| const struct it8xxx2_wuc_cfg *config = dev->config; |
| volatile uint8_t *reg_wuenr = config->reg_wuenr; |
| |
| /* |
| * WUC group only 1, 3, and 4 have enable/disable register, |
| * others are always enabled. |
| */ |
| if (reg_wuenr == IT8XXX2_WUC_UNUSED_REG) { |
| return; |
| } |
| |
| /* Disable wakeup interrupt of the pin */ |
| *reg_wuenr &= ~mask; |
| } |
| |
| void it8xxx2_wuc_clear_status(const struct device *dev, uint8_t mask) |
| { |
| const struct it8xxx2_wuc_cfg *config = dev->config; |
| volatile uint8_t *reg_wuesr = config->reg_wuesr; |
| |
| if (reg_wuesr == IT8XXX2_WUC_UNUSED_REG) { |
| return; |
| } |
| |
| /* W/C wakeup interrupt status of the pin */ |
| *reg_wuesr = mask; |
| } |
| |
| void it8xxx2_wuc_set_polarity(const struct device *dev, uint8_t mask, uint32_t flags) |
| { |
| const struct it8xxx2_wuc_cfg *config = dev->config; |
| volatile uint8_t *reg_wuemr = config->reg_wuemr; |
| volatile uint8_t *reg_wubemr = config->reg_wubemr; |
| |
| if (reg_wuemr == IT8XXX2_WUC_UNUSED_REG) { |
| return; |
| } |
| |
| /* Set wakeup interrupt edge trigger mode of the pin */ |
| if ((flags & WUC_TYPE_EDGE_BOTH) == WUC_TYPE_EDGE_RISING) { |
| *reg_wubemr &= ~mask; |
| *reg_wuemr &= ~mask; |
| } else if ((flags & WUC_TYPE_EDGE_BOTH) == WUC_TYPE_EDGE_FALLING) { |
| *reg_wubemr &= ~mask; |
| *reg_wuemr |= mask; |
| } else { |
| /* Both edge trigger mode */ |
| *reg_wubemr |= mask; |
| } |
| } |
| |
| #define IT8XXX2_WUC_INIT(inst) \ |
| \ |
| static const struct it8xxx2_wuc_cfg it8xxx2_wuc_cfg_##inst = { \ |
| .reg_wuemr = (uint8_t *) DT_INST_REG_ADDR_BY_IDX(inst, 0), \ |
| .reg_wuesr = (uint8_t *) DT_INST_REG_ADDR_BY_IDX(inst, 1), \ |
| .reg_wuenr = (uint8_t *) DT_INST_REG_ADDR_BY_IDX(inst, 2), \ |
| .reg_wubemr = (uint8_t *) DT_INST_REG_ADDR_BY_IDX(inst, 3), \ |
| }; \ |
| \ |
| DEVICE_DT_INST_DEFINE(inst, \ |
| NULL, \ |
| NULL, \ |
| NULL, \ |
| &it8xxx2_wuc_cfg_##inst, \ |
| PRE_KERNEL_1, \ |
| CONFIG_KERNEL_INIT_PRIORITY_OBJECTS, \ |
| NULL); |
| |
| DT_INST_FOREACH_STATUS_OKAY(IT8XXX2_WUC_INIT) |