From 3ddaac19a12cc4a4621b38279a303de6f36fde34 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Sun, 23 Apr 2023 06:58:34 +0000 Subject: [PATCH 01/11] refactor(boards): Move ZMK Uno to power domains. * Add main and sub power domains. * Default necessary Kconfig settings. --- app/boards/shields/zmk_uno/Kconfig.defconfig | 9 ++++ .../zmk_uno/boards/nrf52840dk_nrf52840.conf | 1 + .../boards/nrf52840dk_nrf52840.overlay | 2 +- app/boards/shields/zmk_uno/zmk_uno.dtsi | 48 +++++++++++++++---- 4 files changed, 49 insertions(+), 11 deletions(-) create mode 100644 app/boards/shields/zmk_uno/boards/nrf52840dk_nrf52840.conf diff --git a/app/boards/shields/zmk_uno/Kconfig.defconfig b/app/boards/shields/zmk_uno/Kconfig.defconfig index 95602ca7..617457de 100644 --- a/app/boards/shields/zmk_uno/Kconfig.defconfig +++ b/app/boards/shields/zmk_uno/Kconfig.defconfig @@ -3,6 +3,15 @@ if SHIELD_ZMK_UNO_BASE +config SHIELD_ZMK_UNO_PM + bool "ZMK Uno Automatic Power Management" + default y + select PM_DEVICE + select PM_DEVICE_POWER_DOMAIN + select PM_DEVICE_RUNTIME + select POWER_DOMAIN + select POWER_DOMAIN_GPIO + config ZMK_KEYBOARD_NAME default "ZMK Uno" diff --git a/app/boards/shields/zmk_uno/boards/nrf52840dk_nrf52840.conf b/app/boards/shields/zmk_uno/boards/nrf52840dk_nrf52840.conf new file mode 100644 index 00000000..c94f566c --- /dev/null +++ b/app/boards/shields/zmk_uno/boards/nrf52840dk_nrf52840.conf @@ -0,0 +1 @@ +CONFIG_ZMK_POWER_DOMAINS=y diff --git a/app/boards/shields/zmk_uno/boards/nrf52840dk_nrf52840.overlay b/app/boards/shields/zmk_uno/boards/nrf52840dk_nrf52840.overlay index d798eca7..f1d2f003 100644 --- a/app/boards/shields/zmk_uno/boards/nrf52840dk_nrf52840.overlay +++ b/app/boards/shields/zmk_uno/boards/nrf52840dk_nrf52840.overlay @@ -63,4 +63,4 @@ encoder: &qdec0 { wakeup-sources = <&soft_off_direct_kscan>; }; -}; \ No newline at end of file +}; diff --git a/app/boards/shields/zmk_uno/zmk_uno.dtsi b/app/boards/shields/zmk_uno/zmk_uno.dtsi index 9ea625a4..8fe0c718 100644 --- a/app/boards/shields/zmk_uno/zmk_uno.dtsi +++ b/app/boards/shields/zmk_uno/zmk_uno.dtsi @@ -9,6 +9,22 @@ &arduino_i2c { status = "okay"; + + oled: ssd1306@3c { + compatible = "solomon,ssd1306fb"; + reg = <0x3c>; + label = "DISPLAY"; + width = <128>; + height = <64>; + segment-offset = <0>; + page-offset = <0>; + display-offset = <0>; + multiplex-ratio = <63>; + prechargep = <0x22>; + + power-domain = <&core_power_domain>; + zephyr,pm-device-runtime-auto; + }; }; nice_view_spi: &arduino_spi { @@ -20,11 +36,17 @@ nice_view_spi: &arduino_spi { // on the bus, properly picking up the first `cs-gpios` specifier. ls0xx@0 { reg = <0>; + + power-domain = <&core_power_domain>; + zephyr,pm-device-runtime-auto; }; led_strip: ws2812@0 { compatible = "worldsemi,ws2812-spi"; + power-domain = <&rgb_power>; + zephyr,pm-device-runtime-auto; + /* SPI */ reg = <0>; /* ignored, but necessary for SPI bindings */ spi-max-frequency = <4000000>; @@ -35,6 +57,7 @@ nice_view_spi: &arduino_spi { spi-zero-frame = <0x40>; color-mapping = ; + }; }; @@ -42,19 +65,24 @@ nice_view_spi: &arduino_spi { chosen { zmk,backlight = &backlight; zmk,underglow = &led_strip; + zephyr,display = &oled; }; - // Commented out until we add more powerful power domain support - // external_power { - // compatible = "zmk,ext-power-generic"; - // init-delay-ms = <200>; - // control-gpios = <&arduino_header 1 GPIO_ACTIVE_LOW>; - // }; + core_power_domain: core_power_domain { + compatible = "power-domain-gpio"; + startup-delay-us = <2000>; + off-on-delay-us = <2000>; + enable-gpios = <&arduino_header 0 GPIO_ACTIVE_LOW>; + zephyr,pm-device-runtime-auto; + }; - rgb_power { - compatible = "zmk,ext-power-generic"; - init-delay-ms = <200>; - control-gpios = <&arduino_header 1 GPIO_ACTIVE_LOW>; + rgb_power: rgb_power { + compatible = "power-domain-gpio"; + startup-delay-us = <200>; + off-on-delay-us = <2000>; + enable-gpios = <&arduino_header 1 GPIO_ACTIVE_LOW>; + power-domain = <&core_power_domain>; + zephyr,pm-device-runtime-auto; }; backlight: gpioleds { From 6c1d6fb3e45ab7ba7ea12c69900b3c4caa342792 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Sun, 23 Apr 2023 07:02:11 +0000 Subject: [PATCH 02/11] feat(display): Add device runtime PM handling. * Properly get/put the display device as needed when we start/ stop using it as part of our high level app logic. --- app/src/display/main.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/src/display/main.c b/app/src/display/main.c index e15e2de0..870945c3 100644 --- a/app/src/display/main.c +++ b/app/src/display/main.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -55,7 +56,16 @@ void display_timer_cb() { k_work_submit_to_queue(zmk_display_work_q(), &display_ K_TIMER_DEFINE(display_timer, display_timer_cb, NULL); void unblank_display_cb(struct k_work *work) { + int err = pm_device_runtime_get(display); + if (err < 0) { + LOG_ERR("Failed to get the display device PM (%d)", err); + return; + } + display_blanking_off(display); + + lv_obj_invalidate(lv_scr_act()); + k_timer_start(&display_timer, K_MSEC(TICK_MS), K_MSEC(TICK_MS)); } @@ -64,6 +74,7 @@ void unblank_display_cb(struct k_work *work) { void blank_display_cb(struct k_work *work) { k_timer_stop(&display_timer); display_blanking_on(display); + pm_device_runtime_put(display); } K_WORK_DEFINE(blank_display_work, blank_display_cb); K_WORK_DEFINE(unblank_display_work, unblank_display_cb); From 01ea0e44bda63e9a3f21b6ce8bdfb7b0461f4676 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Sun, 23 Apr 2023 07:10:48 +0000 Subject: [PATCH 03/11] refactor(underglow): Add runtime device PM support * Properly get/put the LED strip instance when actively using the LEDs, to allow automatic power domain handling to cut power when the LEDs are not in use. --- app/Kconfig | 2 +- app/src/rgb_underglow.c | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/app/Kconfig b/app/Kconfig index a45f2dc2..86ff0461 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -275,7 +275,7 @@ config SPI config ZMK_RGB_UNDERGLOW_EXT_POWER bool "RGB underglow toggling also controls external power" - default y + default y if !POWER_DOMAIN config ZMK_RGB_UNDERGLOW_BRT_MIN int "RGB underglow minimum brightness in percent" diff --git a/app/src/rgb_underglow.c b/app/src/rgb_underglow.c index 3453fb44..7f5bdc54 100644 --- a/app/src/rgb_underglow.c +++ b/app/src/rgb_underglow.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -274,6 +275,7 @@ static int zmk_rgb_underglow_init(void) { #endif if (state.on) { + pm_device_runtime_get(led_strip); k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(50)); } @@ -300,6 +302,14 @@ int zmk_rgb_underglow_get_state(bool *on_off) { int zmk_rgb_underglow_on(void) { if (!led_strip) return -ENODEV; + } + + // Newer PM device approach to ensuring powered on when used. + const int rc = pm_device_runtime_get(led_strip); + if (rc < 0) { + LOG_ERR("Failed to enable/get the PM device (%d)", rc); + return rc; + } #if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_EXT_POWER) if (ext_power != NULL) { @@ -345,6 +355,8 @@ int zmk_rgb_underglow_off(void) { k_timer_stop(&underglow_tick); state.on = false; + pm_device_runtime_put(led_strip); + return zmk_rgb_underglow_save_state(); } From 5ccc0b94ca978e9bb7e4052a7cd381c66e97b7e3 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Sun, 23 Apr 2023 00:35:04 -0700 Subject: [PATCH 04/11] REMOVE ME: Move to pete fork/branch with PM work. --- app/west.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/west.yml b/app/west.yml index 1b502477..e2f3d105 100644 --- a/app/west.yml +++ b/app/west.yml @@ -4,10 +4,12 @@ manifest: url-base: https://github.com/zephyrproject-rtos - name: zmkfirmware url-base: https://github.com/zmkfirmware + - name: petejohanson + url-base: https://github.com/petejohanson projects: - name: zephyr - remote: zmkfirmware - revision: v3.5.0+zmk-fixes + remote: petejohanson + revision: v3.5-device-power-management clone-depth: 1 import: name-blocklist: From ce511cb769be938a12c6effb493d98d59a281e41 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Mon, 24 Apr 2023 07:57:17 +0000 Subject: [PATCH 05/11] feat(power): Add power domain config * High level ZMK_POWER_DOMAINS for the feature. * ZMK_POWER_DOMAINS_DYNAMIC_DEFAULT config setting to have various subsystems add their respective devices to the chosen `zmk,default-power-domain` on init. --- app/Kconfig | 39 ++++++++++++++++++++++++++++++--------- app/src/display/Kconfig | 5 +++++ app/src/display/main.c | 14 ++++++++++++++ app/src/rgb_underglow.c | 15 +++++++++++++++ 4 files changed, 64 insertions(+), 9 deletions(-) diff --git a/app/Kconfig b/app/Kconfig index 86ff0461..02b6f829 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -273,9 +273,16 @@ if ZMK_RGB_UNDERGLOW config SPI default y + +config ZMK_RGB_UNDERGLOW_DEFAULT_POWER_DOMAIN + bool "Auto-assign the RGB underglow to the default power domain" + default y + depends on ZMK_POWER_DOMAINS_DYNAMIC_DEFAULT + config ZMK_RGB_UNDERGLOW_EXT_POWER bool "RGB underglow toggling also controls external power" - default y if !POWER_DOMAIN + default y + depends on !ZMK_POWER_DOMAINS config ZMK_RGB_UNDERGLOW_BRT_MIN int "RGB underglow minimum brightness in percent" @@ -338,6 +345,7 @@ config ZMK_RGB_UNDERGLOW_AUTO_OFF_USB bool "Turn off RGB underglow when USB is disconnected" depends on USB_DEVICE_STACK + #ZMK_RGB_UNDERGLOW endif @@ -412,23 +420,36 @@ config ZMK_SLEEP depends on HAS_POWEROFF select POWEROFF select ZMK_PM_DEVICE_SUSPEND_RESUME + select PM_DEVICE imply USB -if ZMK_SLEEP - -config PM_DEVICE - default y - config ZMK_IDLE_SLEEP_TIMEOUT int "Milliseconds of inactivity before entering deep sleep" + depends on ZMK_SLEEP default 900000 -#ZMK_SLEEP -endif +config ZMK_POWER_DOMAINS + bool "Enable automatic power domain handling" + default n + select PM_DEVICE + select PM_DEVICE_POWER_DOMAIN + select PM_DEVICE_RUNTIME + select POWER_DOMAIN + select POWER_DOMAIN_GPIO + +config ZMK_POWER_DOMAINS_DYNAMIC_DEFAULT + bool "Enable assigning peripherals to the chosen default power domain" + default n + depends on ZMK_POWER_DOMAINS + select PM_DEVICE_POWER_DOMAIN_DYNAMIC + +# Default this to 2, the most common scenario for this for ZMK is RGB + OLED +config PM_DEVICE_POWER_DOMAIN_DYNAMIC_NUM + default 2 config ZMK_EXT_POWER bool "Enable support to control external power output" - default y + default y if !ZMK_POWER_DOMAINS config ZMK_PM bool diff --git a/app/src/display/Kconfig b/app/src/display/Kconfig index 1cde0fe4..de8e4a01 100644 --- a/app/src/display/Kconfig +++ b/app/src/display/Kconfig @@ -13,6 +13,11 @@ config ZMK_DISPLAY_BLANK_ON_IDLE bool "Blank display on idle" default y if SSD1306 +config ZMK_DISPLAY_DEFAULT_POWER_DOMAIN + bool "Auto-assign the display to the default power domain" + default y + depends on ZMK_POWER_DOMAINS_DYNAMIC_DEFAULT + if LV_USE_THEME_MONO config ZMK_DISPLAY_INVERT diff --git a/app/src/display/main.c b/app/src/display/main.c index 870945c3..fe276903 100644 --- a/app/src/display/main.c +++ b/app/src/display/main.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -118,6 +119,19 @@ void initialize_display(struct k_work *work) { return; } +#if IS_ENABLED(CONFIG_ZMK_DISPLAY_DEFAULT_POWER_DOMAIN) && DT_HAS_CHOSEN(zmk_default_power_domain) + + pm_device_runtime_enable(display); + if (!pm_device_on_power_domain(display)) { + int rc = + pm_device_power_domain_add(display, DEVICE_DT_GET(DT_CHOSEN(zmk_default_power_domain))); + if (rc < 0) { + LOG_ERR("Failed to add the display to the default power domain (0x%02x)", -rc); + } + } + +#endif + initialized = true; initialize_theme(); diff --git a/app/src/rgb_underglow.c b/app/src/rgb_underglow.c index 7f5bdc54..f14bbc8f 100644 --- a/app/src/rgb_underglow.c +++ b/app/src/rgb_underglow.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -254,6 +255,20 @@ static int zmk_rgb_underglow_init(void) { } #endif +#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_DEFAULT_POWER_DOMAIN) && \ + DT_HAS_CHOSEN(zmk_default_power_domain) + + pm_device_runtime_enable(led_strip); + if (!pm_device_on_power_domain(led_strip)) { + int rc = pm_device_power_domain_add(led_strip, + DEVICE_DT_GET(DT_CHOSEN(zmk_default_power_domain))); + if (rc < 0) { + LOG_ERR("Failed to add the LED strip to the default power domain (0x%02x)", -rc); + } + } + +#endif + state = (struct rgb_underglow_state){ color : { h : CONFIG_ZMK_RGB_UNDERGLOW_HUE_START, From 15e7c43ec0bb1df20df52464c8cd154d50b995df Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Mon, 24 Apr 2023 07:58:23 +0000 Subject: [PATCH 06/11] refactor(boards): Move nice!nano to power domains * Set a chosen `zmk,default-power-domain` * Enable the relevant Kconfig settings for PDs. --- app/boards/arm/nice_nano/Kconfig.board | 4 ++ .../arm/nice_nano/arduino_pro_micro_pins.dtsi | 61 ++++++++++--------- app/boards/arm/nice_nano/nice_nano.dts | 13 ++-- app/boards/arm/nice_nano/nice_nano.dtsi | 1 - app/boards/arm/nice_nano/nice_nano_v2.dts | 14 +++-- 5 files changed, 54 insertions(+), 39 deletions(-) diff --git a/app/boards/arm/nice_nano/Kconfig.board b/app/boards/arm/nice_nano/Kconfig.board index 8dd16512..969bc058 100644 --- a/app/boards/arm/nice_nano/Kconfig.board +++ b/app/boards/arm/nice_nano/Kconfig.board @@ -5,9 +5,13 @@ config BOARD_NICE_NANO bool "nice!nano" + imply ZMK_POWER_DOMAINS + imply ZMK_POWER_DOMAINS_DYNAMIC_DEFAULT depends on SOC_NRF52840_QIAA config BOARD_NICE_NANO_V2 bool "nice!nano v2" + imply ZMK_POWER_DOMAINS + imply ZMK_POWER_DOMAINS_DYNAMIC_DEFAULT depends on SOC_NRF52840_QIAA diff --git a/app/boards/arm/nice_nano/arduino_pro_micro_pins.dtsi b/app/boards/arm/nice_nano/arduino_pro_micro_pins.dtsi index 2c257ef0..115c0cc5 100644 --- a/app/boards/arm/nice_nano/arduino_pro_micro_pins.dtsi +++ b/app/boards/arm/nice_nano/arduino_pro_micro_pins.dtsi @@ -11,25 +11,25 @@ gpio-map-mask = <0xffffffff 0xffffffc0>; gpio-map-pass-thru = <0 0x3f>; gpio-map - = <0 0 &gpio0 8 0> /* D0 */ - , <1 0 &gpio0 6 0> /* D1 */ - , <2 0 &gpio0 17 0> /* D2 */ - , <3 0 &gpio0 20 0> /* D3 */ - , <4 0 &gpio0 22 0> /* D4/A6 */ - , <5 0 &gpio0 24 0> /* D5 */ - , <6 0 &gpio1 0 0> /* D6/A7 */ - , <7 0 &gpio0 11 0> /* D7 */ - , <8 0 &gpio1 4 0> /* D8/A8 */ - , <9 0 &gpio1 6 0> /* D9/A9 */ - , <10 0 &gpio0 9 0> /* D10/A10 */ - , <16 0 &gpio0 10 0> /* D16 */ - , <14 0 &gpio1 11 0> /* D14 */ - , <15 0 &gpio1 13 0> /* D15 */ - , <18 0 &gpio1 15 0> /* D18/A0 */ - , <19 0 &gpio0 2 0> /* D19/A1 */ - , <20 0 &gpio0 29 0> /* D20/A2 */ - , <21 0 &gpio0 31 0> /* D21/A3 */ - ; + = <0 0 &gpio0 8 0> /* D0 */ + , <1 0 &gpio0 6 0> /* D1 */ + , <2 0 &gpio0 17 0> /* D2 */ + , <3 0 &gpio0 20 0> /* D3 */ + , <4 0 &gpio0 22 0> /* D4/A6 */ + , <5 0 &gpio0 24 0> /* D5 */ + , <6 0 &gpio1 0 0> /* D6/A7 */ + , <7 0 &gpio0 11 0> /* D7 */ + , <8 0 &gpio1 4 0> /* D8/A8 */ + , <9 0 &gpio1 6 0> /* D9/A9 */ + , <10 0 &gpio0 9 0> /* D10/A10 */ + , <16 0 &gpio0 10 0> /* D16 */ + , <14 0 &gpio1 11 0> /* D14 */ + , <15 0 &gpio1 13 0> /* D15 */ + , <18 0 &gpio1 15 0> /* D18/A0 */ + , <19 0 &gpio0 2 0> /* D19/A1 */ + , <20 0 &gpio0 29 0> /* D20/A2 */ + , <21 0 &gpio0 31 0> /* D21/A3 */ + ; }; pro_micro_a: connector_a { @@ -38,16 +38,16 @@ gpio-map-mask = <0xffffffff 0xffffffc0>; gpio-map-pass-thru = <0 0x3f>; gpio-map - = <0 0 &gpio1 15 0> /* D18/A0 */ - , <1 0 &gpio0 2 0> /* D19/A1 */ - , <2 0 &gpio0 29 0> /* D20/A2 */ - , <3 0 &gpio0 31 0> /* D21/A3 */ - , <6 0 &gpio0 22 0> /* D4/A6 */ - , <7 0 &gpio1 0 0> /* D6/A7 */ - , <8 0 &gpio1 4 0> /* D8/A8 */ - , <9 0 &gpio1 6 0> /* D9/A9 */ - , <10 0 &gpio0 9 0> /* D10/A10 */ - ; + = <0 0 &gpio1 15 0> /* D18/A0 */ + , <1 0 &gpio0 2 0> /* D19/A1 */ + , <2 0 &gpio0 29 0> /* D20/A2 */ + , <3 0 &gpio0 31 0> /* D21/A3 */ + , <6 0 &gpio0 22 0> /* D4/A6 */ + , <7 0 &gpio1 0 0> /* D6/A7 */ + , <8 0 &gpio1 4 0> /* D8/A8 */ + , <9 0 &gpio1 6 0> /* D9/A9 */ + , <10 0 &gpio0 9 0> /* D10/A10 */ + ; }; }; @@ -55,3 +55,6 @@ pro_micro_d: &pro_micro {}; pro_micro_i2c: &i2c0 {}; pro_micro_spi: &spi1 {}; pro_micro_serial: &uart0 {}; + +pro_micro_power_domain: &core_power_domain {}; + diff --git a/app/boards/arm/nice_nano/nice_nano.dts b/app/boards/arm/nice_nano/nice_nano.dts index 06be88e1..96d39c54 100644 --- a/app/boards/arm/nice_nano/nice_nano.dts +++ b/app/boards/arm/nice_nano/nice_nano.dts @@ -10,12 +10,15 @@ / { chosen { zmk,battery = &vbatt; + zmk,default-power-domain = &core_power_domain; }; - // Node name must match original "EXT_POWER" label to preserve user settings. - EXT_POWER { - compatible = "zmk,ext-power-generic"; - control-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + core_power_domain: core_power_domain { + compatible = "power-domain-gpio", "power-domain"; + startup-delay-us = <50000>; + off-on-delay-us = <50000>; + enable-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + zephyr,pm-device-runtime-auto; }; vbatt: vbatt { @@ -25,3 +28,5 @@ full-ohms = <(2000000 + 806000)>; }; }; + +#include "arduino_pro_micro_pins.dtsi" diff --git a/app/boards/arm/nice_nano/nice_nano.dtsi b/app/boards/arm/nice_nano/nice_nano.dtsi index 839845c8..168169b3 100644 --- a/app/boards/arm/nice_nano/nice_nano.dtsi +++ b/app/boards/arm/nice_nano/nice_nano.dtsi @@ -6,7 +6,6 @@ #include #include "nice_nano-pinctrl.dtsi" -#include "arduino_pro_micro_pins.dtsi" / { model = "nice!nano"; diff --git a/app/boards/arm/nice_nano/nice_nano_v2.dts b/app/boards/arm/nice_nano/nice_nano_v2.dts index c4f7a821..f6719681 100644 --- a/app/boards/arm/nice_nano/nice_nano_v2.dts +++ b/app/boards/arm/nice_nano/nice_nano_v2.dts @@ -10,16 +10,20 @@ / { chosen { zmk,battery = &vbatt; + zmk,default-power-domain = &core_power_domain; }; - // Node name must match original "EXT_POWER" label to preserve user settings. - EXT_POWER { - compatible = "zmk,ext-power-generic"; - control-gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>; - init-delay-ms = <50>; + core_power_domain: core_power_domain { + compatible = "power-domain-gpio", "power-domain"; + startup-delay-us = <50000>; + off-on-delay-us = <50000>; + enable-gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>; + zephyr,pm-device-runtime-auto; }; vbatt: vbatt { compatible = "zmk,battery-nrf-vddh"; }; }; + +#include "arduino_pro_micro_pins.dtsi" From 6f17d9c5d5aea5aa1b8101640665e2fa2e0b14be Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Tue, 12 Sep 2023 19:47:41 -0700 Subject: [PATCH 07/11] refactor(boards): Move puchi_ble to power domains * Set a chosen `zmk,default-power-domain` * Enable the relevant Kconfig settings for PDs. --- app/boards/arm/puchi_ble/Kconfig.board | 2 ++ .../arm/puchi_ble/arduino_pro_micro_pins.dtsi | 2 ++ app/boards/arm/puchi_ble/puchi_ble_v1.dts | 15 +++++++++++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/app/boards/arm/puchi_ble/Kconfig.board b/app/boards/arm/puchi_ble/Kconfig.board index 0f5b7f96..7cf705ad 100644 --- a/app/boards/arm/puchi_ble/Kconfig.board +++ b/app/boards/arm/puchi_ble/Kconfig.board @@ -5,4 +5,6 @@ config BOARD_PUCHI_BLE_v1 bool "puchi_ble_v1" + imply ZMK_POWER_DOMAINS + imply ZMK_POWER_DOMAINS_DYNAMIC_DEFAULT depends on SOC_NRF52840_QIAA diff --git a/app/boards/arm/puchi_ble/arduino_pro_micro_pins.dtsi b/app/boards/arm/puchi_ble/arduino_pro_micro_pins.dtsi index 3037ea3e..84ae136e 100644 --- a/app/boards/arm/puchi_ble/arduino_pro_micro_pins.dtsi +++ b/app/boards/arm/puchi_ble/arduino_pro_micro_pins.dtsi @@ -57,3 +57,5 @@ pro_micro_d: &pro_micro {}; pro_micro_i2c: &i2c0 {}; pro_micro_spi: &spi0 {}; pro_micro_serial: &uart0 {}; + +pro_micro_power_domain: &core_power_domain {}; \ No newline at end of file diff --git a/app/boards/arm/puchi_ble/puchi_ble_v1.dts b/app/boards/arm/puchi_ble/puchi_ble_v1.dts index 9f3194e0..de1281ec 100644 --- a/app/boards/arm/puchi_ble/puchi_ble_v1.dts +++ b/app/boards/arm/puchi_ble/puchi_ble_v1.dts @@ -6,7 +6,6 @@ /dts-v1/; #include -#include "arduino_pro_micro_pins.dtsi" #include "puchi_ble_v1-pinctrl.dtsi" / { @@ -18,6 +17,7 @@ zephyr,sram = &sram0; zephyr,flash = &flash0; zmk,battery = &vbatt; + zmk,default-power-domain = &core_power_domain; }; leds { @@ -33,6 +33,14 @@ control-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; }; + core_power_domain: core_power_domain { + compatible = "power-domain-gpio", "power-domain"; + startup-delay-us = <50000>; + off-on-delay-us = <50000>; + enable-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; + zephyr,pm-device-runtime-auto; + }; + vbatt: vbatt { compatible = "zmk,battery-voltage-divider"; io-channels = <&adc 2>; @@ -79,7 +87,7 @@ zephyr_udc0: &usbd { &flash0 { /* * For more information, see: - * http://docs.zephyrproject.org/latest/devices/dts/flash_partitions.html + * http: //docs.zephyrproject.org/latest/devices/dts/flash_partitions.html */ partitions { compatible = "fixed-partitions"; @@ -111,3 +119,6 @@ zephyr_udc0: &usbd { }; }; }; + +// Included at the end to ensure the power domain DTS node exists +#include "arduino_pro_micro_pins.dtsi" From 84a5ae58fb6ba84dbe5710ec6be89ec44d5578d6 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Sun, 28 Jan 2024 16:53:35 -0800 Subject: [PATCH 08/11] fix(power): Tweaks for dynamic PD support. --- app/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Kconfig b/app/Kconfig index 02b6f829..7059ed28 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -442,6 +442,7 @@ config ZMK_POWER_DOMAINS_DYNAMIC_DEFAULT default n depends on ZMK_POWER_DOMAINS select PM_DEVICE_POWER_DOMAIN_DYNAMIC + select DEVICE_DEPS_DYNAMIC # Default this to 2, the most common scenario for this for ZMK is RGB + OLED config PM_DEVICE_POWER_DOMAIN_DYNAMIC_NUM From 742063629be04ceb8b179dd9590ca01d21320157 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Sun, 28 Jan 2024 16:54:18 -0800 Subject: [PATCH 09/11] refactor(shields): Use dynamic display PD for ZMK Uno. --- app/boards/shields/zmk_uno/Kconfig.defconfig | 2 ++ app/boards/shields/zmk_uno/zmk_uno.dtsi | 21 ++++---------------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/app/boards/shields/zmk_uno/Kconfig.defconfig b/app/boards/shields/zmk_uno/Kconfig.defconfig index 617457de..8d2ab18b 100644 --- a/app/boards/shields/zmk_uno/Kconfig.defconfig +++ b/app/boards/shields/zmk_uno/Kconfig.defconfig @@ -6,6 +6,8 @@ if SHIELD_ZMK_UNO_BASE config SHIELD_ZMK_UNO_PM bool "ZMK Uno Automatic Power Management" default y + select ZMK_POWER_DOMAINS + select ZMK_POWER_DOMAINS_DYNAMIC_DEFAULT select PM_DEVICE select PM_DEVICE_POWER_DOMAIN select PM_DEVICE_RUNTIME diff --git a/app/boards/shields/zmk_uno/zmk_uno.dtsi b/app/boards/shields/zmk_uno/zmk_uno.dtsi index 8fe0c718..cd2cbeec 100644 --- a/app/boards/shields/zmk_uno/zmk_uno.dtsi +++ b/app/boards/shields/zmk_uno/zmk_uno.dtsi @@ -9,22 +9,6 @@ &arduino_i2c { status = "okay"; - - oled: ssd1306@3c { - compatible = "solomon,ssd1306fb"; - reg = <0x3c>; - label = "DISPLAY"; - width = <128>; - height = <64>; - segment-offset = <0>; - page-offset = <0>; - display-offset = <0>; - multiplex-ratio = <63>; - prechargep = <0x22>; - - power-domain = <&core_power_domain>; - zephyr,pm-device-runtime-auto; - }; }; nice_view_spi: &arduino_spi { @@ -66,10 +50,13 @@ nice_view_spi: &arduino_spi { zmk,backlight = &backlight; zmk,underglow = &led_strip; zephyr,display = &oled; + zmk,display-default-power-domain = &core_power_domain; }; core_power_domain: core_power_domain { - compatible = "power-domain-gpio"; + // The "power-domain" compatible is needed for any PDs used for that have dynamic deps, + // e.g. for displays or RGB not assigned to the PD in the devicetree statically. + compatible = "power-domain-gpio", "power-domain"; startup-delay-us = <2000>; off-on-delay-us = <2000>; enable-gpios = <&arduino_header 0 GPIO_ACTIVE_LOW>; From 2f37b08ee36e800a5bd71e4f6e8260f098841f23 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Sun, 28 Jan 2024 16:55:06 -0800 Subject: [PATCH 10/11] fix(power): Fixes for dynamic PD in display/RGB. --- app/src/display/main.c | 14 +++++++++----- app/src/rgb_underglow.c | 24 ++++++++++++------------ 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/app/src/display/main.c b/app/src/display/main.c index fe276903..43281c5e 100644 --- a/app/src/display/main.c +++ b/app/src/display/main.c @@ -111,6 +111,13 @@ static void initialize_theme() { #endif // CONFIG_LV_USE_THEME_MONO } +#define HAS_DISPLAY_PD \ + (DT_HAS_CHOSEN(zmk_display_default_power_domain) || DT_HAS_CHOSEN(zmk_default_power_domain)) +#define GET_DISPLAY_PD \ + DEVICE_DT_GET(COND_CODE_1(DT_HAS_CHOSEN(zmk_display_default_power_domain), \ + (DT_CHOSEN(zmk_display_default_power_domain)), \ + (DT_CHOSEN(zmk_default_power_domain)))) + void initialize_display(struct k_work *work) { LOG_DBG(""); @@ -119,17 +126,14 @@ void initialize_display(struct k_work *work) { return; } -#if IS_ENABLED(CONFIG_ZMK_DISPLAY_DEFAULT_POWER_DOMAIN) && DT_HAS_CHOSEN(zmk_default_power_domain) - +#if IS_ENABLED(CONFIG_ZMK_DISPLAY_DEFAULT_POWER_DOMAIN) && HAS_DISPLAY_PD pm_device_runtime_enable(display); if (!pm_device_on_power_domain(display)) { - int rc = - pm_device_power_domain_add(display, DEVICE_DT_GET(DT_CHOSEN(zmk_default_power_domain))); + int rc = pm_device_power_domain_add(display, GET_DISPLAY_PD); if (rc < 0) { LOG_ERR("Failed to add the display to the default power domain (0x%02x)", -rc); } } - #endif initialized = true; diff --git a/app/src/rgb_underglow.c b/app/src/rgb_underglow.c index f14bbc8f..2bf2c6e6 100644 --- a/app/src/rgb_underglow.c +++ b/app/src/rgb_underglow.c @@ -62,7 +62,7 @@ struct rgb_underglow_state { bool on; }; -static const struct device *led_strip; +static const struct device *led_strip = DEVICE_DT_GET(STRIP_CHOSEN); static struct led_rgb pixels[STRIP_NUM_PIXELS]; @@ -245,9 +245,15 @@ static void zmk_rgb_underglow_save_state_work(struct k_work *_work) { static struct k_work_delayable underglow_save_work; #endif -static int zmk_rgb_underglow_init(void) { - led_strip = DEVICE_DT_GET(STRIP_CHOSEN); +#define HAS_RGB_UG_PD \ + (DT_HAS_CHOSEN(zmk_rgb_underglow_default_power_domain) || \ + DT_HAS_CHOSEN(zmk_default_power_domain)) +#define GET_RGB_UG_PD \ + DEVICE_DT_GET(COND_CODE_1(DT_HAS_CHOSEN(zmk_rgb_underglow_default_power_domain), \ + (DT_CHOSEN(zmk_rgb_underglow_default_power_domain)), \ + (DT_CHOSEN(zmk_default_power_domain)))) +static int zmk_rgb_underglow_init(void) { #if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_EXT_POWER) if (!device_is_ready(ext_power)) { LOG_ERR("External power device \"%s\" is not ready", ext_power->name); @@ -255,13 +261,11 @@ static int zmk_rgb_underglow_init(void) { } #endif -#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_DEFAULT_POWER_DOMAIN) && \ - DT_HAS_CHOSEN(zmk_default_power_domain) +#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_DEFAULT_POWER_DOMAIN) && HAS_RGB_UG_PD pm_device_runtime_enable(led_strip); if (!pm_device_on_power_domain(led_strip)) { - int rc = pm_device_power_domain_add(led_strip, - DEVICE_DT_GET(DT_CHOSEN(zmk_default_power_domain))); + int rc = pm_device_power_domain_add(led_strip, GET_RGB_UG_PD); if (rc < 0) { LOG_ERR("Failed to add the LED strip to the default power domain (0x%02x)", -rc); } @@ -315,12 +319,8 @@ int zmk_rgb_underglow_get_state(bool *on_off) { } int zmk_rgb_underglow_on(void) { - if (!led_strip) - return -ENODEV; - } - // Newer PM device approach to ensuring powered on when used. - const int rc = pm_device_runtime_get(led_strip); + int rc = pm_device_runtime_get(led_strip); if (rc < 0) { LOG_ERR("Failed to enable/get the PM device (%d)", rc); return rc; From 5f1a1b2cd17332b1611f158a4217765b51008eaf Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Fri, 5 Jul 2024 00:34:03 -0600 Subject: [PATCH 11/11] fix: kscan driver device runtime PM include fix. --- app/module/drivers/kscan/kscan_gpio_direct.c | 1 + app/module/drivers/kscan/kscan_gpio_matrix.c | 1 + app/src/kscan_sideband_behaviors.c | 1 + 3 files changed, 3 insertions(+) diff --git a/app/module/drivers/kscan/kscan_gpio_direct.c b/app/module/drivers/kscan/kscan_gpio_direct.c index 245e78b5..eaf33ec7 100644 --- a/app/module/drivers/kscan/kscan_gpio_direct.c +++ b/app/module/drivers/kscan/kscan_gpio_direct.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include diff --git a/app/module/drivers/kscan/kscan_gpio_matrix.c b/app/module/drivers/kscan/kscan_gpio_matrix.c index e0c76395..42e953e3 100644 --- a/app/module/drivers/kscan/kscan_gpio_matrix.c +++ b/app/module/drivers/kscan/kscan_gpio_matrix.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff --git a/app/src/kscan_sideband_behaviors.c b/app/src/kscan_sideband_behaviors.c index 602cae12..b32c7ce5 100644 --- a/app/src/kscan_sideband_behaviors.c +++ b/app/src/kscan_sideband_behaviors.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include