diff options
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.c | 103 |
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); |