summaryrefslogtreecommitdiff
path: root/zephyr/drivers/cros_kb_raw/cros_kb_raw_ite.c
diff options
context:
space:
mode:
Diffstat (limited to 'zephyr/drivers/cros_kb_raw/cros_kb_raw_ite.c')
-rw-r--r--zephyr/drivers/cros_kb_raw/cros_kb_raw_ite.c103
1 files changed, 82 insertions, 21 deletions
diff --git a/zephyr/drivers/cros_kb_raw/cros_kb_raw_ite.c b/zephyr/drivers/cros_kb_raw/cros_kb_raw_ite.c
index 61b1adcf3f..d5b84cb0fd 100644
--- a/zephyr/drivers/cros_kb_raw/cros_kb_raw_ite.c
+++ b/zephyr/drivers/cros_kb_raw/cros_kb_raw_ite.c
@@ -9,8 +9,11 @@
#include <drivers/cros_kb_raw.h>
#include <drivers/clock_control.h>
#include <drivers/gpio.h>
+#include <drivers/interrupt_controller/wuc_ite_it8xxx2.h>
+#include <dt-bindings/interrupt-controller/it8xxx2-wuc.h>
#include <kernel.h>
#include <soc.h>
+#include <soc_dt.h>
#include <soc/ite_it8xxx2/reg_def_cros.h>
#include "ec_tasks.h"
@@ -20,14 +23,29 @@
#include <logging/log.h>
LOG_MODULE_REGISTER(cros_kb_raw, LOG_LEVEL_ERR);
+#define KEYBOARD_KSI_PIN_COUNT IT8XXX2_DT_INST_WUCCTRL_LEN(0)
#define KSOH_PIN_MASK (((1 << (KEYBOARD_COLS_MAX - 8)) - 1) & 0xff)
/* Device config */
+struct cros_kb_raw_wuc_map_cfg {
+ /* WUC control device structure */
+ const struct device *wucs;
+ /* WUC pin mask */
+ uint8_t mask;
+};
+
struct cros_kb_raw_ite_config {
/* keyboard scan controller base address */
- uintptr_t base;
+ struct kscan_it8xxx2_regs *base;
/* Keyboard scan input (KSI) wake-up irq */
int irq;
+ /* KSI[7:0] wake-up input source configuration list */
+ const struct cros_kb_raw_wuc_map_cfg *wuc_map_list;
+};
+
+struct cros_kb_raw_ite_data {
+ /* KSI[7:0] wake-up interrupt status mask */
+ uint8_t ksi_pin_mask;
};
static int kb_raw_ite_init(const struct device *dev)
@@ -43,9 +61,17 @@ static int cros_kb_raw_ite_enable_interrupt(const struct device *dev,
int enable)
{
const struct cros_kb_raw_ite_config *config = dev->config;
+ struct cros_kb_raw_ite_data *data = dev->data;
if (enable) {
- ECREG(IT8XXX2_WUC_WUESR3) = 0xFF;
+ /*
+ * W/C wakeup interrupt status of KSI[7:0] pins
+ *
+ * NOTE: We want to clear the status as soon as possible,
+ * so clear KSI[7:0] pins at a time.
+ */
+ it8xxx2_wuc_clear_status(config->wuc_map_list[0].wucs,
+ data->ksi_pin_mask);
ite_intc_isr_clear(config->irq);
irq_enable(config->irq);
} else {
@@ -58,8 +84,7 @@ static int cros_kb_raw_ite_enable_interrupt(const struct device *dev,
static int cros_kb_raw_ite_read_row(const struct device *dev)
{
const struct cros_kb_raw_ite_config *config = dev->config;
- struct kscan_it8xxx2_regs *const inst =
- (struct kscan_it8xxx2_regs *) config->base;
+ struct kscan_it8xxx2_regs *const inst = config->base;
/* Bits are active-low, so invert returned levels */
return ((inst->KBS_KSI) ^ 0xff);
@@ -70,8 +95,7 @@ static int cros_kb_raw_ite_drive_column(const struct device *dev, int col)
int mask;
unsigned int key;
const struct cros_kb_raw_ite_config *config = dev->config;
- struct kscan_it8xxx2_regs *const inst =
- (struct kscan_it8xxx2_regs *) config->base;
+ struct kscan_it8xxx2_regs *const inst = config->base;
/* Tri-state all outputs */
if (col == KEYBOARD_COLUMN_NONE)
@@ -105,14 +129,21 @@ static int cros_kb_raw_ite_drive_column(const struct device *dev, int col)
static void cros_kb_raw_ite_ksi_isr(const struct device *dev)
{
- ARG_UNUSED(dev);
+ const struct cros_kb_raw_ite_config *config = dev->config;
+ struct cros_kb_raw_ite_data *data = dev->data;
/*
* We clear IT8XXX2_IRQ_WKINTC irq status in
* ite_intc_irq_handler(), after interrupt was fired.
*/
- /* W/C wakeup interrupt status for KSI[0-7] */
- ECREG(IT8XXX2_WUC_WUESR3) = 0xFF;
+ /*
+ * W/C wakeup interrupt status of KSI[7:0] pins
+ *
+ * NOTE: We want to clear the status as soon as possible,
+ * so clear KSI[7:0] pins at a time.
+ */
+ it8xxx2_wuc_clear_status(config->wuc_map_list[0].wucs,
+ data->ksi_pin_mask);
/* Wake-up keyboard scan task */
task_wake(TASK_ID_KEYSCAN);
@@ -122,8 +153,8 @@ static int cros_kb_raw_ite_init(const struct device *dev)
{
unsigned int key;
const struct cros_kb_raw_ite_config *config = dev->config;
- struct kscan_it8xxx2_regs *const inst =
- (struct kscan_it8xxx2_regs *) config->base;
+ struct cros_kb_raw_ite_data *data = dev->data;
+ struct kscan_it8xxx2_regs *const inst = config->base;
/* Ensure top-level interrupt is disabled */
cros_kb_raw_ite_enable_interrupt(dev, 0);
@@ -158,15 +189,38 @@ static int cros_kb_raw_ite_init(const struct device *dev)
inst->KBS_KSOH1 &= ~KSOH_PIN_MASK;
/* restore interrupts */
irq_unlock(key);
- /* Select falling-edge triggered of wakeup interrupt for KSI[0-7] */
- ECREG(IT8XXX2_WUC_WUEMR3) = 0xFF;
- /* W/C wakeup interrupt status for KSI[0-7] */
- ECREG(IT8XXX2_WUC_WUESR3) = 0xFF;
+
+ for (int i = 0; i < KEYBOARD_KSI_PIN_COUNT; i++) {
+ /* Select wakeup interrupt falling-edge triggered of KSI[7:0] */
+ it8xxx2_wuc_set_polarity(config->wuc_map_list[i].wucs,
+ config->wuc_map_list[i].mask,
+ WUC_TYPE_EDGE_FALLING);
+ /* W/C wakeup interrupt status of KSI[7:0] pins */
+ it8xxx2_wuc_clear_status(config->wuc_map_list[i].wucs,
+ config->wuc_map_list[i].mask);
+ /* Enable wakeup interrupt of KSI[7:0] pins */
+ it8xxx2_wuc_enable(config->wuc_map_list[i].wucs,
+ config->wuc_map_list[i].mask);
+
+ /*
+ * We want to clear KSI[7:0] pins status at a time when wakeup
+ * interrupt fire, so gather the KSI[7:0] pin mask value here.
+ */
+ if (IS_ENABLED(CONFIG_LOG)) {
+ if (config->wuc_map_list[i].wucs !=
+ config->wuc_map_list[0].wucs) {
+ LOG_ERR("KSI%d isn't in the same wuc node!", i);
+ }
+ }
+ data->ksi_pin_mask |= config->wuc_map_list[i].mask;
+ }
+
+ /* W/C interrupt status of KSI[7:0] pins */
ite_intc_isr_clear(config->irq);
- /* Enable wakeup interrupt for KSI[0-7] */
- ECREG(IT8XXX2_WUC_WUENR3) = 0xFF;
- IRQ_CONNECT(DT_INST_IRQN(0), 0, cros_kb_raw_ite_ksi_isr, NULL, 0);
+ irq_connect_dynamic(config->irq, 0,
+ (void (*)(const void *))cros_kb_raw_ite_ksi_isr,
+ (const void *)dev, 0);
return 0;
}
@@ -177,12 +231,19 @@ static const struct cros_kb_raw_driver_api cros_kb_raw_ite_driver_api = {
.read_rows = cros_kb_raw_ite_read_row,
.enable_interrupt = cros_kb_raw_ite_enable_interrupt,
};
+static const struct cros_kb_raw_wuc_map_cfg
+ cros_kb_raw_wuc_0[IT8XXX2_DT_INST_WUCCTRL_LEN(0)] =
+ IT8XXX2_DT_WUC_ITEMS_LIST(0);
static const struct cros_kb_raw_ite_config cros_kb_raw_cfg = {
- .base = DT_INST_REG_ADDR(0),
+ .base = (struct kscan_it8xxx2_regs *)DT_INST_REG_ADDR(0),
.irq = DT_INST_IRQN(0),
+ .wuc_map_list = cros_kb_raw_wuc_0,
};
-DEVICE_DT_INST_DEFINE(0, kb_raw_ite_init, NULL, NULL, &cros_kb_raw_cfg,
- PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
+static struct cros_kb_raw_ite_data cros_kb_raw_data;
+
+DEVICE_DT_INST_DEFINE(0, kb_raw_ite_init, NULL, &cros_kb_raw_data,
+ &cros_kb_raw_cfg, PRE_KERNEL_1,
+ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&cros_kb_raw_ite_driver_api);