driver: input: implement input PM function

Add the pm device for rts5912 input driver

Signed-off-by: Lin Yu-Cheng <lin_yu_cheng@realtek.com>
This commit is contained in:
Lin Yu-Cheng
2025-08-12 16:01:13 +08:00
committed by Johan Hedberg
parent ffdf184b86
commit ad320ee4f2
3 changed files with 241 additions and 39 deletions

View File

@@ -59,7 +59,19 @@
&ksi2_gpio066 &ksi3_gpio067
&ksi4_gpio068 &ksi5_gpio069
&ksi6_gpio070 &ksi7_gpio071>;
pinctrl-names = "default";
pinctrl-1 = <&kso0_sleep_gpio041 &kso1_sleep_gpio042
&kso2_sleep_gpio043 &kso3_sleep_gpio044
&kso4_sleep_gpio045 &kso5_sleep_gpio046
&kso6_sleep_gpio047 &kso7_sleep_gpio048
&kso8_sleep_gpio049 &kso9_sleep_gpio050
&kso10_sleep_gpio051 &kso11_sleep_gpio055
&kso12_sleep_gpio056 &kso13_sleep_gpio057
&kso14_sleep_gpio058 &kso15_sleep_gpio059
&ksi0_gpio064 &ksi1_gpio065
&ksi2_gpio066 &ksi3_gpio067
&ksi4_gpio068 &ksi5_gpio069
&ksi6_gpio070 &ksi7_gpio071>;
pinctrl-names = "default", "sleep";
row-size = <8>;
col-size = <16>;
};

View File

@@ -20,15 +20,11 @@ LOG_MODULE_REGISTER(input_realtek_rts5912_kbd, CONFIG_INPUT_LOG_LEVEL);
struct rts5912_kbd_config {
struct input_kbd_matrix_common_config common;
/* Keyboard scan controller base address */
volatile struct kbm_regs *base;
/* Keyboard scan input (KSI) wake-up irq */
uint32_t irq;
/* KSI/KSO keyboard scan alternate configuration */
const struct pinctrl_dev_config *pcfg;
const struct device *clk_dev;
struct rts5912_sccon_subsys sccon_cfg;
/* For user ignore specific pin of kso*/
uint32_t kso_ignore_mask;
};
@@ -47,18 +43,14 @@ static void rts5912_kbd_drive_column(const struct device *dev, int col)
uint32_t kso_val;
uint32_t key;
/* Tri-state all outputs */
if (col == INPUT_KBD_MATRIX_COLUMN_DRIVE_NONE) {
kso_val = kso_mask;
/* Assert all outputs */
} else if (col == INPUT_KBD_MATRIX_COLUMN_DRIVE_ALL) {
kso_val = 0;
/* Assert a single output */
} else {
kso_val = kso_mask ^ BIT(col);
}
/* Set KSO output data */
key = irq_lock();
inst->scan_out = kso_val;
irq_unlock(key);
@@ -71,7 +63,6 @@ static kbd_row_t rts5912_kbd_read_row(const struct device *dev)
const struct input_kbd_matrix_common_config *common = &config->common;
const uint32_t ksi_mask = BIT_MASK(common->row_size);
/* Bits are active-low, so toggle it (return 1 means key pressed) */
return (inst->scan_in ^ ksi_mask);
}
@@ -85,7 +76,6 @@ static void rts5912_intc_isr_clear(const struct device *dev)
static void rts5912_kbd_isr(const struct device *dev)
{
/* W/C interrupt status of KSI pins */
rts5912_intc_isr_clear(dev);
input_kbd_matrix_poll_start(dev);
}
@@ -95,7 +85,6 @@ static void rts5912_kbd_set_detect_mode(const struct device *dev, bool enable)
const struct rts5912_kbd_config *config = dev->config;
if (enable) {
/* W/C interrupt status of KSI pins */
rts5912_intc_isr_clear(dev);
irq_enable(config->irq);
@@ -114,20 +103,14 @@ static int rts5912_kbd_init(const struct device *dev)
const uint32_t kso_mask = BIT_MASK(common->col_size) & ~config->kso_ignore_mask;
const uint32_t ksi_mask = BIT_MASK(common->row_size);
uint32_t status;
int ret;
/* Disable wakeup and interrupt of KSI pins before configuring */
rts5912_kbd_set_detect_mode(dev, false);
/*
* Enable the internal pull-up and kbs mode of the KSI pins.
* Enable the internal pull-up and kbs mode of the KSO pins.
* Enable the open-drain mode of the KSO pins.
*/
status = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
if (status < 0) {
LOG_ERR("Failed to configure KSI and KSO pins");
return status;
ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
if (ret < 0) {
LOG_ERR("Failed to configure KSI and KSO pins: %d", ret);
return ret;
}
if (!device_is_ready(config->clk_dev)) {
@@ -135,53 +118,154 @@ static int rts5912_kbd_init(const struct device *dev)
return -ENODEV;
}
status = clock_control_on(config->clk_dev, (clock_control_subsys_t)&config->sccon_cfg);
if (status != 0) {
LOG_ERR("kbd clock power on fail");
return status;
ret = clock_control_on(config->clk_dev, (clock_control_subsys_t)&config->sccon_cfg);
if (ret != 0) {
LOG_ERR("kbd clock power on fail: %d", ret);
return ret;
}
/* KSO pins output low */
inst->scan_out = 0x00;
/* Enable KSI 8 if RAW Size more than 8*/
if (ksi_mask & BIT(8)) {
inst->ctrl |= KBM_CTRL_KSI8EN_Msk;
}
/* Enable KSI 9 if RAW Size more than 9*/
if (ksi_mask & BIT(9)) {
inst->ctrl |= KBM_CTRL_KSI9EN_Msk;
}
/* Enable KSO 18 if COL Size more than 18*/
if (kso_mask & BIT(18)) {
inst->ctrl |= KBM_CTRL_KSO18EN_Msk;
}
/* Enable KSO 19 if COL Size more than 19*/
if (kso_mask & BIT(19)) {
inst->ctrl |= KBM_CTRL_KSO19EN_Msk;
}
/* Enable KSO OpenDrain Output Type */
inst->ctrl |= KBM_CTRL_KSOTYPE_Msk;
/* Enable Scan Interrupt*/
inst->int_en |= ksi_mask;
/* W/C interrupt status of KSI pins */
rts5912_intc_isr_clear(dev);
NVIC_ClearPendingIRQ(DT_INST_IRQN(0));
/* Interrupts are enabled in the thread function */
IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority),
rts5912_kbd_isr, DEVICE_DT_INST_GET(0), 0);
IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), rts5912_kbd_isr,
DEVICE_DT_INST_GET(0), 0);
return input_kbd_matrix_common_init(dev);
}
#if defined(CONFIG_PM_DEVICE)
static int input_kbd_matrix_pm_action_suspend(const struct device *dev)
{
const struct rts5912_kbd_config *config = dev->config;
const struct input_kbd_matrix_common_config *common = &config->common;
volatile struct kbm_regs *inst = config->base;
const uint32_t kso_mask = BIT_MASK(common->col_size) & ~config->kso_ignore_mask;
int ret;
ret = clock_control_off(config->clk_dev, (clock_control_subsys_t)&config->sccon_cfg);
if (ret != 0) {
LOG_ERR("clock_control_off failed: %d", ret);
return ret;
}
inst->int_en = 0;
rts5912_intc_isr_clear(dev);
if (kso_mask & BIT(18)) {
inst->ctrl &= ~KBM_CTRL_KSO18EN_Msk;
}
if (kso_mask & BIT(19)) {
inst->ctrl &= ~KBM_CTRL_KSO19EN_Msk;
}
inst->scan_out = 0x00;
inst->ctrl &= ~KBM_CTRL_KSOTYPE_Msk;
ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP);
if (ret < 0) {
LOG_ERR("pinctrl_apply_state failed: %d", ret);
return ret;
}
return 0;
}
static int input_kbd_matrix_pm_action_resume(const struct device *dev)
{
const struct rts5912_kbd_config *config = dev->config;
const struct input_kbd_matrix_common_config *common = &config->common;
volatile struct kbm_regs *inst = config->base;
const uint32_t kso_mask = BIT_MASK(common->col_size) & ~config->kso_ignore_mask;
const uint32_t ksi_mask = BIT_MASK(common->row_size);
int ret;
ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
if (ret < 0) {
LOG_ERR("pinctrl_apply_state failed: %d", ret);
return ret;
}
inst->ctrl |= KBM_CTRL_KSOTYPE_Msk;
inst->scan_out = 0x00;
if (kso_mask & BIT(18)) {
inst->ctrl |= KBM_CTRL_KSO18EN_Msk;
}
if (kso_mask & BIT(19)) {
inst->ctrl |= KBM_CTRL_KSO19EN_Msk;
}
inst->int_en |= ksi_mask;
ret = clock_control_on(config->clk_dev, (clock_control_subsys_t)&config->sccon_cfg);
if (ret != 0) {
LOG_ERR("clock_control_on failed: %d", ret);
return ret;
}
return 0;
}
static int input_kbd_matrix_pm_action_rts5912(const struct device *dev,
enum pm_device_action action)
{
int ret;
switch (action) {
case PM_DEVICE_ACTION_RESUME:
ret = input_kbd_matrix_pm_action_resume(dev);
if (ret != 0) {
LOG_ERR("kbd rts5912 resume fail: %d", ret);
return ret;
}
ret = input_kbd_matrix_pm_action(dev, action);
if (ret != 0) {
LOG_ERR("kbd pm resume fail: %d", ret);
return ret;
}
break;
case PM_DEVICE_ACTION_SUSPEND:
ret = input_kbd_matrix_pm_action_suspend(dev);
if (ret != 0) {
LOG_ERR("kbd rts5912 suspend fail: %d", ret);
return ret;
}
ret = input_kbd_matrix_pm_action(dev, action);
if (ret != 0) {
LOG_ERR("kbd pm suspend fail: %d", ret);
return ret;
}
break;
default:
return -ENOTSUP;
}
return 0;
}
#endif
PINCTRL_DT_INST_DEFINE(0);
INPUT_KBD_MATRIX_DT_INST_DEFINE(0);
@@ -207,7 +291,7 @@ static const struct rts5912_kbd_config rts5912_kbd_cfg_0 = {
static struct rts5912_kbd_data rts5912_kbd_data_0;
PM_DEVICE_DT_INST_DEFINE(0, input_kbd_matrix_pm_action);
PM_DEVICE_DT_INST_DEFINE(0, input_kbd_matrix_pm_action_rts5912);
DEVICE_DT_INST_DEFINE(0, &rts5912_kbd_init, PM_DEVICE_DT_INST_GET(0), &rts5912_kbd_data_0,
&rts5912_kbd_cfg_0, POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, NULL);

View File

@@ -449,6 +449,112 @@
};
/* KSO PINCTRL SETTING END */
/* KSO PINCTRL SLEEP SETTING START */
/omit-if-no-ref/ kso0_sleep_gpio041: kso0_sleep_gpio041 {
pinmux = <REALTEK_RTS5912_PINMUX(41, FUNC0)>;
output-enable;
output-low;
};
/omit-if-no-ref/ kso1_sleep_gpio042: kso1_sleep_gpio042 {
pinmux = <REALTEK_RTS5912_PINMUX(42, FUNC0)>;
output-enable;
output-low;
};
/omit-if-no-ref/ kso2_sleep_gpio043: kso2_sleep_gpio043 {
pinmux = <REALTEK_RTS5912_PINMUX(43, FUNC0)>;
output-enable;
output-low;
};
/omit-if-no-ref/ kso3_sleep_gpio044: kso3_sleep_gpio044 {
pinmux = <REALTEK_RTS5912_PINMUX(44, FUNC0)>;
output-enable;
output-low;
};
/omit-if-no-ref/ kso4_sleep_gpio045: kso4_sleep_gpio045 {
pinmux = <REALTEK_RTS5912_PINMUX(45, FUNC0)>;
output-enable;
output-low;
};
/omit-if-no-ref/ kso5_sleep_gpio046: kso5_sleep_gpio046 {
pinmux = <REALTEK_RTS5912_PINMUX(46, FUNC0)>;
output-enable;
output-low;
};
/omit-if-no-ref/ kso6_sleep_gpio047: kso6_sleep_gpio047 {
pinmux = <REALTEK_RTS5912_PINMUX(47, FUNC0)>;
output-enable;
output-low;
};
/omit-if-no-ref/ kso7_sleep_gpio048: kso7_sleep_gpio048 {
pinmux = <REALTEK_RTS5912_PINMUX(48, FUNC0)>;
output-enable;
output-low;
};
/omit-if-no-ref/ kso8_sleep_gpio049: kso8_sleep_gpio049 {
pinmux = <REALTEK_RTS5912_PINMUX(49, FUNC0)>;
output-enable;
output-low;
};
/omit-if-no-ref/ kso9_sleep_gpio050: kso9_sleep_gpio050 {
pinmux = <REALTEK_RTS5912_PINMUX(50, FUNC0)>;
output-enable;
output-low;
};
/omit-if-no-ref/ kso10_sleep_gpio051: kso10_sleep_gpio051 {
pinmux = <REALTEK_RTS5912_PINMUX(51, FUNC0)>;
output-enable;
output-low;
};
/omit-if-no-ref/ kso11_sleep_gpio055: kso11_sleep_gpio055 {
pinmux = <REALTEK_RTS5912_PINMUX(55, FUNC0)>;
output-enable;
output-low;
};
/omit-if-no-ref/ kso12_sleep_gpio056: kso12_sleep_gpio056 {
pinmux = <REALTEK_RTS5912_PINMUX(56, FUNC0)>;
output-enable;
output-low;
};
/omit-if-no-ref/ kso13_sleep_gpio057: kso13_sleep_gpio057 {
pinmux = <REALTEK_RTS5912_PINMUX(57, FUNC0)>;
output-enable;
output-low;
};
/omit-if-no-ref/ kso14_sleep_gpio058: kso14_sleep_gpio058 {
pinmux = <REALTEK_RTS5912_PINMUX(58, FUNC0)>;
output-enable;
output-low;
};
/omit-if-no-ref/ kso15_sleep_gpio059: kso15_sleep_gpio059 {
pinmux = <REALTEK_RTS5912_PINMUX(59, FUNC0)>;
output-enable;
output-low;
};
/omit-if-no-ref/ kso16_sleep_gpio060: kso16_sleep_gpio060 {
pinmux = <REALTEK_RTS5912_PINMUX(60, FUNC0)>;
output-enable;
output-low;
};
/omit-if-no-ref/ kso17_sleep_gpio061: kso17_sleep_gpio061 {
pinmux = <REALTEK_RTS5912_PINMUX(61, FUNC0)>;
output-enable;
output-low;
};
/omit-if-no-ref/ kso18_sleep_gpio092: kso18_sleep_gpio092 {
pinmux = <REALTEK_RTS5912_PINMUX(92, FUNC0)>;
output-enable;
output-low;
};
/omit-if-no-ref/ kso19_sleep_gpio093: kso19_sleep_gpio093 {
pinmux = <REALTEK_RTS5912_PINMUX(93, FUNC0)>;
output-enable;
output-low;
};
/* KSO PINCTRL SLEEP SETTING END */
/* KSI PINCTRL SETTING START */
/omit-if-no-ref/ ksi0_gpio064: ksi0_gpio064 {
pinmux = <REALTEK_RTS5912_PINMUX(64, FUNC1)>;