diff --git a/app/boards/shields/zmk_uno/zmk_uno.overlay b/app/boards/shields/zmk_uno/zmk_uno.overlay
index 3d105abf..6948112b 100644
--- a/app/boards/shields/zmk_uno/zmk_uno.overlay
+++ b/app/boards/shields/zmk_uno/zmk_uno.overlay
@@ -38,6 +38,8 @@
 
     endpoint_sideband_behaviors {
         compatible = "zmk,kscan-sideband-behaviors";
+
+        auto-enable;
         kscan = <&kscan_sp3t_toggle>;
 
         first_toggle_sideband: first_toggle_sideband {
diff --git a/app/dts/bindings/kscan/zmk,kscan-sideband-behaviors.yaml b/app/dts/bindings/kscan/zmk,kscan-sideband-behaviors.yaml
index f3ed180d..e38beeb4 100644
--- a/app/dts/bindings/kscan/zmk,kscan-sideband-behaviors.yaml
+++ b/app/dts/bindings/kscan/zmk,kscan-sideband-behaviors.yaml
@@ -11,6 +11,9 @@ compatible: "zmk,kscan-sideband-behaviors"
 include: kscan.yaml
 
 properties:
+  auto-enable:
+    type: boolean
+
   kscan:
     type: phandle
     required: true
diff --git a/app/module/drivers/kscan/kscan_gpio_charlieplex.c b/app/module/drivers/kscan/kscan_gpio_charlieplex.c
index 3ecbcd6a..f48a6a2f 100644
--- a/app/module/drivers/kscan/kscan_gpio_charlieplex.c
+++ b/app/module/drivers/kscan/kscan_gpio_charlieplex.c
@@ -12,6 +12,7 @@
 #include <zephyr/drivers/kscan.h>
 #include <zephyr/kernel.h>
 #include <zephyr/logging/log.h>
+#include <zephyr/pm/device.h>
 #include <zephyr/sys/__assert.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;
 }
 
+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,
                                                  const gpio_flags_t flags) {
     const struct kscan_charlieplex_config *config = dev->config;
@@ -359,11 +375,7 @@ static int kscan_charlieplex_init_interrupt(const struct device *dev) {
     return err;
 }
 
-static int kscan_charlieplex_init(const struct device *dev) {
-    struct kscan_charlieplex_data *data = dev->data;
-
-    data->dev = dev;
-
+static void kscan_charlieplex_setup_pins(const struct device *dev) {
     kscan_charlieplex_init_inputs(dev);
     kscan_charlieplex_set_all_outputs(dev, 0);
 
@@ -371,7 +383,46 @@ static int kscan_charlieplex_init(const struct device *dev) {
     if (config->use_interrupt) {
         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);
+
+#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;
 }
 
@@ -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, (.interrupt = KSCAN_INTR_CFG_INIT(n), ))};                  \
                                                                                                    \
-    DEVICE_DT_INST_DEFINE(n, &kscan_charlieplex_init, NULL, &kscan_charlieplex_data_##n,           \
-                          &kscan_charlieplex_config_##n, POST_KERNEL, CONFIG_KSCAN_INIT_PRIORITY,  \
-                          &kscan_charlieplex_api);
+    PM_DEVICE_DT_INST_DEFINE(n, kscan_charlieplex_pm_action);                                      \
+                                                                                                   \
+    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);
diff --git a/app/module/drivers/kscan/kscan_gpio_direct.c b/app/module/drivers/kscan/kscan_gpio_direct.c
index fa24e69e..245e78b5 100644
--- a/app/module/drivers/kscan/kscan_gpio_direct.c
+++ b/app/module/drivers/kscan/kscan_gpio_direct.c
@@ -294,6 +294,24 @@ static int kscan_direct_init_input_inst(const struct device *dev, const struct g
     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) {
     const struct kscan_direct_data *data = dev->data;
     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.
     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);
 
-    k_work_init_delayable(&data->work, kscan_direct_work_handler);
+#endif
 
     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) {
     switch (action) {
     case PM_DEVICE_ACTION_SUSPEND:
+        kscan_direct_disconnect_inputs(dev);
         return kscan_direct_disable(dev);
     case PM_DEVICE_ACTION_RESUME:
+        kscan_direct_init_inputs(dev);
         return kscan_direct_enable(dev);
     default:
         return -ENOTSUP;
diff --git a/app/module/drivers/kscan/kscan_gpio_matrix.c b/app/module/drivers/kscan/kscan_gpio_matrix.c
index 8a3c39f2..e0c76395 100644
--- a/app/module/drivers/kscan/kscan_gpio_matrix.c
+++ b/app/module/drivers/kscan/kscan_gpio_matrix.c
@@ -405,6 +405,44 @@ static int kscan_matrix_init_outputs(const struct device *dev) {
     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) {
     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.
     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);
 
+#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;
 }
 
@@ -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) {
     switch (action) {
     case PM_DEVICE_ACTION_SUSPEND:
+        kscan_matrix_disconnect_inputs(dev);
+        kscan_matrix_disconnect_outputs(dev);
+
         return kscan_matrix_disable(dev);
     case PM_DEVICE_ACTION_RESUME:
+        kscan_matrix_setup_pins(dev);
         return kscan_matrix_enable(dev);
     default:
         return -ENOTSUP;
diff --git a/app/src/kscan_sideband_behaviors.c b/app/src/kscan_sideband_behaviors.c
index f3992ebc..602cae12 100644
--- a/app/src/kscan_sideband_behaviors.c
+++ b/app/src/kscan_sideband_behaviors.c
@@ -26,6 +26,7 @@ struct ksbb_entry {
 
 struct ksbb_config {
     const struct device *kscan;
+    bool auto_enable;
     struct ksbb_entry *entries;
     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) {
-    const struct ksbb_config *cfg = dev->config;
     struct ksbb_data *data = dev->data;
 
     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;
 }
 
 static int ksbb_enable(const struct device *dev) {
     struct ksbb_data *data = dev->data;
+    const struct ksbb_config *config = dev->config;
     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;
 }
 
 static int ksbb_disable(const struct device *dev) {
     struct ksbb_data *data = dev->data;
+    const struct ksbb_config *config = dev->config;
     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;
 }
 
+#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) {
     const struct ksbb_config *config = dev->config;
 
@@ -129,8 +161,16 @@ static int ksbb_init(const struct device *dev) {
         return -ENODEV;
     }
 
-    kscan_config(config->kscan, &ksbb_inner_kscan_callback);
-    kscan_enable_callback(config->kscan);
+    if (config->auto_enable) {
+#if !IS_ENABLED(CONFIG_PM_DEVICE)
+        kscan_config(config->kscan, &ksbb_inner_kscan_callback);
+        kscan_enable_callback(config->kscan);
+#else
+        ksbb_pm_action(dev, PM_DEVICE_ACTION_RESUME);
+    } else {
+        pm_device_init_suspended(dev);
+#endif
+    }
 
     return 0;
 }
@@ -141,21 +181,6 @@ static const struct kscan_driver_api ksbb_api = {
     .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)                                                                                   \
     {                                                                                              \
         .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, (, ))};                                    \
     const struct ksbb_config ksbb_config_##n = {                                                   \
         .kscan = DEVICE_DT_GET(DT_INST_PHANDLE(n, kscan)),                                         \
+        .auto_enable = DT_INST_PROP_OR(n, auto_enable, false),                                     \
         .entries = entries_##n,                                                                    \
         .entries_len = ARRAY_SIZE(entries_##n),                                                    \
     };                                                                                             \
     struct ksbb_data ksbb_data_##n = {};                                                           \
     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,                  \
-                          &ksbb_config_##n, APPLICATION,                                           \
+                          &ksbb_config_##n, POST_KERNEL,                                           \
                           CONFIG_ZMK_KSCAN_SIDEBAND_BEHAVIORS_INIT_PRIORITY, &ksbb_api);
 
 DT_INST_FOREACH_STATUS_OKAY(KSBB_INST)
diff --git a/docs/docs/features/soft-off.md b/docs/docs/features/soft-off.md
index 7018afa0..207bb13f 100644
--- a/docs/docs/features/soft-off.md
+++ b/docs/docs/features/soft-off.md
@@ -121,6 +121,7 @@ With that in place, the kscan sideband behavior will wrap the new driver:
         compatible = "zmk,kscan-sideband-behaviors";
 
         kscan = <&soft_off_direct_scan>;
+        auto-enable;
         wakeup-source;
 
         soft_off {