input: it8xxx2_kbd: mask out KSOL and KSOH1 register access

KSOL and KSOH1 registers are used not only by the kbd driver, but
potentially by other GPIOs attached to the keyboard scanning pins. Mask
write access to those registers to ensure drivers don't step over each
other.

Signed-off-by: Fabio Baltieri <fabiobaltieri@google.com>
This commit is contained in:
Fabio Baltieri 2024-04-29 10:48:46 +01:00 committed by Alberto Escolar
parent 2e36c898c9
commit d8476170bf

View file

@ -16,6 +16,7 @@
#include <zephyr/input/input.h>
#include <zephyr/input/input_kbd_matrix.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/util_macro.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(input_ite_it8xxx2_kbd);
@ -58,24 +59,27 @@ static void it8xxx2_kbd_drive_column(const struct device *dev, int col)
const struct it8xxx2_kbd_config *const config = dev->config;
const struct input_kbd_matrix_common_config *common = &config->common;
struct kscan_it8xxx2_regs *const inst = config->base;
int mask;
const uint32_t kso_mask = BIT_MASK(common->col_size);
const uint8_t ksol_mask = kso_mask & 0xff;
const uint8_t ksoh1_mask = (kso_mask >> 8) & 0xff;
uint32_t kso_val;
/* Tri-state all outputs */
if (col == INPUT_KBD_MATRIX_COLUMN_DRIVE_NONE) {
mask = 0x3ffff;
kso_val = kso_mask;
/* Assert all outputs */
} else if (col == INPUT_KBD_MATRIX_COLUMN_DRIVE_ALL) {
mask = 0;
kso_val = 0;
/* Assert a single output */
} else {
mask = 0x3ffff ^ BIT(col);
kso_val = kso_mask ^ BIT(col);
}
/* Set KSO[17:0] output data */
inst->KBS_KSOL = (uint8_t) (mask & 0xff);
inst->KBS_KSOH1 = (uint8_t) ((mask >> 8) & 0xff);
inst->KBS_KSOL = (inst->KBS_KSOL & ~ksol_mask) | (kso_val & ksol_mask);
inst->KBS_KSOH1 = (inst->KBS_KSOH1 & ~ksoh1_mask) | ((kso_val >> 8) & ksoh1_mask);
if (common->col_size > 16) {
inst->KBS_KSOH2 = (uint8_t) ((mask >> 16) & 0xff);
inst->KBS_KSOH2 = (kso_val >> 16) & 0xff;
}
}
@ -138,6 +142,9 @@ static int it8xxx2_kbd_init(const struct device *dev)
const struct input_kbd_matrix_common_config *common = &config->common;
struct it8xxx2_kbd_data *data = dev->data;
struct kscan_it8xxx2_regs *const inst = config->base;
const uint32_t kso_mask = BIT_MASK(common->col_size);
const uint8_t ksol_mask = kso_mask & 0xff;
const uint8_t ksoh1_mask = (kso_mask >> 8) & 0xff;
int status;
/* Disable wakeup and interrupt of KSI pins before configuring */
@ -171,8 +178,8 @@ static int it8xxx2_kbd_init(const struct device *dev)
}
/* KSO[17:0] pins output low */
inst->KBS_KSOL = 0x00;
inst->KBS_KSOH1 = 0x00;
inst->KBS_KSOL = inst->KBS_KSOL & ~ksol_mask;
inst->KBS_KSOH1 = inst->KBS_KSOH1 & ~ksoh1_mask;
if (common->col_size > 16) {
inst->KBS_KSOH2 = 0x00;
}