feat(kscan): More complete PM support to drivers.
* Update our GPIO kscan drivers to more completely support PM device, by doing proper hardare init/deinit in the PM action hook.
This commit is contained in:
parent
c5cca5b34f
commit
0438cb0ee5
7 changed files with 203 additions and 38 deletions
|
@ -38,6 +38,8 @@
|
||||||
|
|
||||||
endpoint_sideband_behaviors {
|
endpoint_sideband_behaviors {
|
||||||
compatible = "zmk,kscan-sideband-behaviors";
|
compatible = "zmk,kscan-sideband-behaviors";
|
||||||
|
|
||||||
|
auto-enable;
|
||||||
kscan = <&kscan_sp3t_toggle>;
|
kscan = <&kscan_sp3t_toggle>;
|
||||||
|
|
||||||
first_toggle_sideband: first_toggle_sideband {
|
first_toggle_sideband: first_toggle_sideband {
|
||||||
|
|
|
@ -11,6 +11,9 @@ compatible: "zmk,kscan-sideband-behaviors"
|
||||||
include: kscan.yaml
|
include: kscan.yaml
|
||||||
|
|
||||||
properties:
|
properties:
|
||||||
|
auto-enable:
|
||||||
|
type: boolean
|
||||||
|
|
||||||
kscan:
|
kscan:
|
||||||
type: phandle
|
type: phandle
|
||||||
required: true
|
required: true
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <zephyr/drivers/kscan.h>
|
#include <zephyr/drivers/kscan.h>
|
||||||
#include <zephyr/kernel.h>
|
#include <zephyr/kernel.h>
|
||||||
#include <zephyr/logging/log.h>
|
#include <zephyr/logging/log.h>
|
||||||
|
#include <zephyr/pm/device.h>
|
||||||
#include <zephyr/sys/__assert.h>
|
#include <zephyr/sys/__assert.h>
|
||||||
#include <zephyr/sys/util.h>
|
#include <zephyr/sys/util.h>
|
||||||
|
|
||||||
|
@ -167,6 +168,21 @@ static int kscan_charlieplex_set_all_outputs(const struct device *dev, const int
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int kscan_charlieplex_disconnect_all(const struct device *dev) {
|
||||||
|
const struct kscan_charlieplex_config *config = dev->config;
|
||||||
|
|
||||||
|
for (int i = 0; i < config->cells.len; i++) {
|
||||||
|
const struct gpio_dt_spec *gpio = &config->cells.gpios[i];
|
||||||
|
int err = gpio_pin_configure_dt(gpio, GPIO_DISCONNECTED);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("Unable to configure pin %u on %s for input", gpio->pin, gpio->port->name);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int kscan_charlieplex_interrupt_configure(const struct device *dev,
|
static int kscan_charlieplex_interrupt_configure(const struct device *dev,
|
||||||
const gpio_flags_t flags) {
|
const gpio_flags_t flags) {
|
||||||
const struct kscan_charlieplex_config *config = dev->config;
|
const struct kscan_charlieplex_config *config = dev->config;
|
||||||
|
@ -359,11 +375,7 @@ static int kscan_charlieplex_init_interrupt(const struct device *dev) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kscan_charlieplex_init(const struct device *dev) {
|
static void kscan_charlieplex_setup_pins(const struct device *dev) {
|
||||||
struct kscan_charlieplex_data *data = dev->data;
|
|
||||||
|
|
||||||
data->dev = dev;
|
|
||||||
|
|
||||||
kscan_charlieplex_init_inputs(dev);
|
kscan_charlieplex_init_inputs(dev);
|
||||||
kscan_charlieplex_set_all_outputs(dev, 0);
|
kscan_charlieplex_set_all_outputs(dev, 0);
|
||||||
|
|
||||||
|
@ -371,7 +383,46 @@ static int kscan_charlieplex_init(const struct device *dev) {
|
||||||
if (config->use_interrupt) {
|
if (config->use_interrupt) {
|
||||||
kscan_charlieplex_init_interrupt(dev);
|
kscan_charlieplex_init_interrupt(dev);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_PM_DEVICE)
|
||||||
|
|
||||||
|
static int kscan_charlieplex_pm_action(const struct device *dev, enum pm_device_action action) {
|
||||||
|
switch (action) {
|
||||||
|
case PM_DEVICE_ACTION_SUSPEND:
|
||||||
|
kscan_charlieplex_interrupt_configure(dev, GPIO_INT_DISABLE);
|
||||||
|
kscan_charlieplex_disconnect_all(dev);
|
||||||
|
|
||||||
|
return kscan_charlieplex_disable(dev);
|
||||||
|
case PM_DEVICE_ACTION_RESUME:
|
||||||
|
kscan_charlieplex_setup_pins(dev);
|
||||||
|
|
||||||
|
return kscan_charlieplex_enable(dev);
|
||||||
|
default:
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // IS_ENABLED(CONFIG_PM_DEVICE)
|
||||||
|
|
||||||
|
static int kscan_charlieplex_init(const struct device *dev) {
|
||||||
|
struct kscan_charlieplex_data *data = dev->data;
|
||||||
|
|
||||||
|
data->dev = dev;
|
||||||
|
|
||||||
k_work_init_delayable(&data->work, kscan_charlieplex_work_handler);
|
k_work_init_delayable(&data->work, kscan_charlieplex_work_handler);
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_PM_DEVICE)
|
||||||
|
pm_device_init_suspended(dev);
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)
|
||||||
|
pm_device_runtime_enable(dev);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
kscan_charlieplex_setup_pins(dev);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,8 +457,10 @@ static const struct kscan_driver_api kscan_charlieplex_api = {
|
||||||
COND_THIS_INTERRUPT(n, (.use_interrupt = INST_INTR_DEFINED(n), )) \
|
COND_THIS_INTERRUPT(n, (.use_interrupt = INST_INTR_DEFINED(n), )) \
|
||||||
COND_THIS_INTERRUPT(n, (.interrupt = KSCAN_INTR_CFG_INIT(n), ))}; \
|
COND_THIS_INTERRUPT(n, (.interrupt = KSCAN_INTR_CFG_INIT(n), ))}; \
|
||||||
\
|
\
|
||||||
DEVICE_DT_INST_DEFINE(n, &kscan_charlieplex_init, NULL, &kscan_charlieplex_data_##n, \
|
PM_DEVICE_DT_INST_DEFINE(n, kscan_charlieplex_pm_action); \
|
||||||
&kscan_charlieplex_config_##n, POST_KERNEL, CONFIG_KSCAN_INIT_PRIORITY, \
|
\
|
||||||
&kscan_charlieplex_api);
|
DEVICE_DT_INST_DEFINE(n, &kscan_charlieplex_init, PM_DEVICE_DT_INST_GET(n), \
|
||||||
|
&kscan_charlieplex_data_##n, &kscan_charlieplex_config_##n, POST_KERNEL, \
|
||||||
|
CONFIG_KSCAN_INIT_PRIORITY, &kscan_charlieplex_api);
|
||||||
|
|
||||||
DT_INST_FOREACH_STATUS_OKAY(KSCAN_CHARLIEPLEX_INIT);
|
DT_INST_FOREACH_STATUS_OKAY(KSCAN_CHARLIEPLEX_INIT);
|
||||||
|
|
|
@ -294,6 +294,24 @@ static int kscan_direct_init_input_inst(const struct device *dev, const struct g
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_PM_DEVICE)
|
||||||
|
|
||||||
|
static int kscan_direct_disconnect_inputs(const struct device *dev) {
|
||||||
|
const struct kscan_direct_data *data = dev->data;
|
||||||
|
|
||||||
|
for (int i = 0; i < data->inputs.len; i++) {
|
||||||
|
const struct gpio_dt_spec *gpio = &data->inputs.gpios[i].spec;
|
||||||
|
int err = gpio_pin_configure_dt(gpio, GPIO_DISCONNECTED);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // IS_ENABLED(CONFIG_PM_DEVICE)
|
||||||
|
|
||||||
static int kscan_direct_init_inputs(const struct device *dev) {
|
static int kscan_direct_init_inputs(const struct device *dev) {
|
||||||
const struct kscan_direct_data *data = dev->data;
|
const struct kscan_direct_data *data = dev->data;
|
||||||
const struct kscan_direct_config *config = dev->config;
|
const struct kscan_direct_config *config = dev->config;
|
||||||
|
@ -317,9 +335,20 @@ static int kscan_direct_init(const struct device *dev) {
|
||||||
// Sort inputs by port so we can read each port just once per scan.
|
// Sort inputs by port so we can read each port just once per scan.
|
||||||
kscan_gpio_list_sort_by_port(&data->inputs);
|
kscan_gpio_list_sort_by_port(&data->inputs);
|
||||||
|
|
||||||
|
k_work_init_delayable(&data->work, kscan_direct_work_handler);
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_PM_DEVICE)
|
||||||
|
pm_device_init_suspended(dev);
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)
|
||||||
|
pm_device_runtime_enable(dev);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
kscan_direct_init_inputs(dev);
|
kscan_direct_init_inputs(dev);
|
||||||
|
|
||||||
k_work_init_delayable(&data->work, kscan_direct_work_handler);
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -329,8 +358,10 @@ static int kscan_direct_init(const struct device *dev) {
|
||||||
static int kscan_direct_pm_action(const struct device *dev, enum pm_device_action action) {
|
static int kscan_direct_pm_action(const struct device *dev, enum pm_device_action action) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case PM_DEVICE_ACTION_SUSPEND:
|
case PM_DEVICE_ACTION_SUSPEND:
|
||||||
|
kscan_direct_disconnect_inputs(dev);
|
||||||
return kscan_direct_disable(dev);
|
return kscan_direct_disable(dev);
|
||||||
case PM_DEVICE_ACTION_RESUME:
|
case PM_DEVICE_ACTION_RESUME:
|
||||||
|
kscan_direct_init_inputs(dev);
|
||||||
return kscan_direct_enable(dev);
|
return kscan_direct_enable(dev);
|
||||||
default:
|
default:
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
|
|
|
@ -405,6 +405,44 @@ static int kscan_matrix_init_outputs(const struct device *dev) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_PM_DEVICE)
|
||||||
|
|
||||||
|
static int kscan_matrix_disconnect_inputs(const struct device *dev) {
|
||||||
|
const struct kscan_matrix_data *data = dev->data;
|
||||||
|
|
||||||
|
for (int i = 0; i < data->inputs.len; i++) {
|
||||||
|
const struct gpio_dt_spec *gpio = &data->inputs.gpios[i].spec;
|
||||||
|
int err = gpio_pin_configure_dt(gpio, GPIO_DISCONNECTED);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int kscan_matrix_disconnect_outputs(const struct device *dev) {
|
||||||
|
const struct kscan_matrix_config *config = dev->config;
|
||||||
|
|
||||||
|
for (int i = 0; i < config->outputs.len; i++) {
|
||||||
|
const struct gpio_dt_spec *gpio = &config->outputs.gpios[i].spec;
|
||||||
|
int err = gpio_pin_configure_dt(gpio, GPIO_DISCONNECTED);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // IS_ENABLED(CONFIG_PM_DEVICE)
|
||||||
|
|
||||||
|
static void kscan_matrix_setup_pins(const struct device *dev) {
|
||||||
|
kscan_matrix_init_inputs(dev);
|
||||||
|
kscan_matrix_init_outputs(dev);
|
||||||
|
kscan_matrix_set_all_outputs(dev, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static int kscan_matrix_init(const struct device *dev) {
|
static int kscan_matrix_init(const struct device *dev) {
|
||||||
struct kscan_matrix_data *data = dev->data;
|
struct kscan_matrix_data *data = dev->data;
|
||||||
|
|
||||||
|
@ -413,12 +451,19 @@ static int kscan_matrix_init(const struct device *dev) {
|
||||||
// Sort inputs by port so we can read each port just once per scan.
|
// Sort inputs by port so we can read each port just once per scan.
|
||||||
kscan_gpio_list_sort_by_port(&data->inputs);
|
kscan_gpio_list_sort_by_port(&data->inputs);
|
||||||
|
|
||||||
kscan_matrix_init_inputs(dev);
|
|
||||||
kscan_matrix_init_outputs(dev);
|
|
||||||
kscan_matrix_set_all_outputs(dev, 0);
|
|
||||||
|
|
||||||
k_work_init_delayable(&data->work, kscan_matrix_work_handler);
|
k_work_init_delayable(&data->work, kscan_matrix_work_handler);
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_PM_DEVICE)
|
||||||
|
pm_device_init_suspended(dev);
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)
|
||||||
|
pm_device_runtime_enable(dev);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
kscan_matrix_setup_pins(dev);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,8 +472,12 @@ static int kscan_matrix_init(const struct device *dev) {
|
||||||
static int kscan_matrix_pm_action(const struct device *dev, enum pm_device_action action) {
|
static int kscan_matrix_pm_action(const struct device *dev, enum pm_device_action action) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case PM_DEVICE_ACTION_SUSPEND:
|
case PM_DEVICE_ACTION_SUSPEND:
|
||||||
|
kscan_matrix_disconnect_inputs(dev);
|
||||||
|
kscan_matrix_disconnect_outputs(dev);
|
||||||
|
|
||||||
return kscan_matrix_disable(dev);
|
return kscan_matrix_disable(dev);
|
||||||
case PM_DEVICE_ACTION_RESUME:
|
case PM_DEVICE_ACTION_RESUME:
|
||||||
|
kscan_matrix_setup_pins(dev);
|
||||||
return kscan_matrix_enable(dev);
|
return kscan_matrix_enable(dev);
|
||||||
default:
|
default:
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
|
|
|
@ -26,6 +26,7 @@ struct ksbb_entry {
|
||||||
|
|
||||||
struct ksbb_config {
|
struct ksbb_config {
|
||||||
const struct device *kscan;
|
const struct device *kscan;
|
||||||
|
bool auto_enable;
|
||||||
struct ksbb_entry *entries;
|
struct ksbb_entry *entries;
|
||||||
size_t entries_len;
|
size_t entries_len;
|
||||||
};
|
};
|
||||||
|
@ -93,34 +94,65 @@ void ksbb_inner_kscan_callback(const struct device *dev, uint32_t row, uint32_t
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ksbb_configure(const struct device *dev, kscan_callback_t callback) {
|
static int ksbb_configure(const struct device *dev, kscan_callback_t callback) {
|
||||||
const struct ksbb_config *cfg = dev->config;
|
|
||||||
struct ksbb_data *data = dev->data;
|
struct ksbb_data *data = dev->data;
|
||||||
|
|
||||||
data->callback = callback;
|
data->callback = callback;
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_PM_DEVICE)
|
|
||||||
if (pm_device_wakeup_is_enabled(dev) && pm_device_wakeup_is_capable(cfg->kscan)) {
|
|
||||||
pm_device_wakeup_enable(cfg->kscan, true);
|
|
||||||
}
|
|
||||||
#endif // IS_ENABLED(CONFIG_PM_DEVICE)
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ksbb_enable(const struct device *dev) {
|
static int ksbb_enable(const struct device *dev) {
|
||||||
struct ksbb_data *data = dev->data;
|
struct ksbb_data *data = dev->data;
|
||||||
|
const struct ksbb_config *config = dev->config;
|
||||||
data->enabled = true;
|
data->enabled = true;
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)
|
||||||
|
if (!pm_device_runtime_is_enabled(dev) && pm_device_runtime_is_enabled(config->kscan)) {
|
||||||
|
pm_device_runtime_get(config->kscan);
|
||||||
|
}
|
||||||
|
#elif IS_ENABLED(CONFIG_PM_DEVICE)
|
||||||
|
pm_device_action_run(config->kscan, PM_DEVICE_ACTION_RESUME);
|
||||||
|
#endif // IS_ENABLED(CONFIG_PM_DEVICE)
|
||||||
|
|
||||||
|
kscan_config(config->kscan, &ksbb_inner_kscan_callback);
|
||||||
|
kscan_enable_callback(config->kscan);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ksbb_disable(const struct device *dev) {
|
static int ksbb_disable(const struct device *dev) {
|
||||||
struct ksbb_data *data = dev->data;
|
struct ksbb_data *data = dev->data;
|
||||||
|
const struct ksbb_config *config = dev->config;
|
||||||
data->enabled = false;
|
data->enabled = false;
|
||||||
|
|
||||||
|
kscan_disable_callback(config->kscan);
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)
|
||||||
|
if (!pm_device_runtime_is_enabled(dev) && pm_device_runtime_is_enabled(config->kscan)) {
|
||||||
|
pm_device_runtime_put(config->kscan);
|
||||||
|
}
|
||||||
|
#elif IS_ENABLED(CONFIG_PM_DEVICE)
|
||||||
|
pm_device_action_run(config->kscan, PM_DEVICE_ACTION_SUSPEND);
|
||||||
|
#endif // IS_ENABLED(CONFIG_PM_DEVICE)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_PM_DEVICE)
|
||||||
|
|
||||||
|
static int ksbb_pm_action(const struct device *dev, enum pm_device_action action) {
|
||||||
|
switch (action) {
|
||||||
|
case PM_DEVICE_ACTION_SUSPEND:
|
||||||
|
return ksbb_disable(dev);
|
||||||
|
case PM_DEVICE_ACTION_RESUME:
|
||||||
|
return ksbb_enable(dev);
|
||||||
|
default:
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // IS_ENABLED(CONFIG_PM_DEVICE)
|
||||||
|
|
||||||
static int ksbb_init(const struct device *dev) {
|
static int ksbb_init(const struct device *dev) {
|
||||||
const struct ksbb_config *config = dev->config;
|
const struct ksbb_config *config = dev->config;
|
||||||
|
|
||||||
|
@ -129,8 +161,16 @@ static int ksbb_init(const struct device *dev) {
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config->auto_enable) {
|
||||||
|
#if !IS_ENABLED(CONFIG_PM_DEVICE)
|
||||||
kscan_config(config->kscan, &ksbb_inner_kscan_callback);
|
kscan_config(config->kscan, &ksbb_inner_kscan_callback);
|
||||||
kscan_enable_callback(config->kscan);
|
kscan_enable_callback(config->kscan);
|
||||||
|
#else
|
||||||
|
ksbb_pm_action(dev, PM_DEVICE_ACTION_RESUME);
|
||||||
|
} else {
|
||||||
|
pm_device_init_suspended(dev);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -141,21 +181,6 @@ static const struct kscan_driver_api ksbb_api = {
|
||||||
.disable_callback = ksbb_disable,
|
.disable_callback = ksbb_disable,
|
||||||
};
|
};
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_PM_DEVICE)
|
|
||||||
|
|
||||||
static int ksbb_pm_action(const struct device *dev, enum pm_device_action action) {
|
|
||||||
switch (action) {
|
|
||||||
case PM_DEVICE_ACTION_SUSPEND:
|
|
||||||
return ksbb_disable(dev);
|
|
||||||
case PM_DEVICE_ACTION_RESUME:
|
|
||||||
return ksbb_disable(dev);
|
|
||||||
default:
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // IS_ENABLED(CONFIG_PM_DEVICE)
|
|
||||||
|
|
||||||
#define ENTRY(e) \
|
#define ENTRY(e) \
|
||||||
{ \
|
{ \
|
||||||
.row = DT_PROP(e, row), .column = DT_PROP(e, column), \
|
.row = DT_PROP(e, row), .column = DT_PROP(e, column), \
|
||||||
|
@ -167,13 +192,14 @@ static int ksbb_pm_action(const struct device *dev, enum pm_device_action action
|
||||||
DT_INST_FOREACH_CHILD_STATUS_OKAY_SEP(n, ENTRY, (, ))}; \
|
DT_INST_FOREACH_CHILD_STATUS_OKAY_SEP(n, ENTRY, (, ))}; \
|
||||||
const struct ksbb_config ksbb_config_##n = { \
|
const struct ksbb_config ksbb_config_##n = { \
|
||||||
.kscan = DEVICE_DT_GET(DT_INST_PHANDLE(n, kscan)), \
|
.kscan = DEVICE_DT_GET(DT_INST_PHANDLE(n, kscan)), \
|
||||||
|
.auto_enable = DT_INST_PROP_OR(n, auto_enable, false), \
|
||||||
.entries = entries_##n, \
|
.entries = entries_##n, \
|
||||||
.entries_len = ARRAY_SIZE(entries_##n), \
|
.entries_len = ARRAY_SIZE(entries_##n), \
|
||||||
}; \
|
}; \
|
||||||
struct ksbb_data ksbb_data_##n = {}; \
|
struct ksbb_data ksbb_data_##n = {}; \
|
||||||
PM_DEVICE_DT_INST_DEFINE(n, ksbb_pm_action); \
|
PM_DEVICE_DT_INST_DEFINE(n, ksbb_pm_action); \
|
||||||
DEVICE_DT_INST_DEFINE(n, ksbb_init, PM_DEVICE_DT_INST_GET(n), &ksbb_data_##n, \
|
DEVICE_DT_INST_DEFINE(n, ksbb_init, PM_DEVICE_DT_INST_GET(n), &ksbb_data_##n, \
|
||||||
&ksbb_config_##n, APPLICATION, \
|
&ksbb_config_##n, POST_KERNEL, \
|
||||||
CONFIG_ZMK_KSCAN_SIDEBAND_BEHAVIORS_INIT_PRIORITY, &ksbb_api);
|
CONFIG_ZMK_KSCAN_SIDEBAND_BEHAVIORS_INIT_PRIORITY, &ksbb_api);
|
||||||
|
|
||||||
DT_INST_FOREACH_STATUS_OKAY(KSBB_INST)
|
DT_INST_FOREACH_STATUS_OKAY(KSBB_INST)
|
||||||
|
|
|
@ -121,6 +121,7 @@ With that in place, the kscan sideband behavior will wrap the new driver:
|
||||||
compatible = "zmk,kscan-sideband-behaviors";
|
compatible = "zmk,kscan-sideband-behaviors";
|
||||||
|
|
||||||
kscan = <&soft_off_direct_scan>;
|
kscan = <&soft_off_direct_scan>;
|
||||||
|
auto-enable;
|
||||||
wakeup-source;
|
wakeup-source;
|
||||||
|
|
||||||
soft_off {
|
soft_off {
|
||||||
|
|
Loading…
Add table
Reference in a new issue