diff --git a/core/embed/projects/kernel/main.c b/core/embed/projects/kernel/main.c index f252907bd8..42ad8992cb 100644 --- a/core/embed/projects/kernel/main.c +++ b/core/embed/projects/kernel/main.c @@ -55,6 +55,10 @@ #include #endif +#ifdef USE_POWERCTL +#include +#endif + #ifdef USE_PVD #include #endif @@ -100,6 +104,10 @@ static void optiga_log_hex(const char *prefix, const uint8_t *data, #endif void drivers_init() { +#ifdef USE_POWERCTL + powerctl_init(); +#endif + #ifdef USE_TAMPER tamper_init(); #endif diff --git a/core/embed/sys/powerctl/inc/sys/powerctl.h b/core/embed/sys/powerctl/inc/sys/powerctl.h new file mode 100644 index 0000000000..45dfd49dae --- /dev/null +++ b/core/embed/sys/powerctl/inc/sys/powerctl.h @@ -0,0 +1,58 @@ +/* + * This file is part of the Trezor project, https://trezor.io/ + * + * Copyright (c) SatoshiLabs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef TREZORHAL_POWERCTL_H +#define TREZORHAL_POWERCTL_H + +// Initializes power control module. +// +// Returns true if the initialization was successful. +bool powerctl_init(void); + +// Deinitializes power control module. +void powerctl_deinit(void); + +typedef enum { + POWER_SOURCE_BATT, + POWER_SOURCE_USB, + POWER_SOURCE_QI, +} power_source_t; + +typedef struct { + // Current power source + power_source_t power_source; + // Set if charging is active + bool charging; + // Battery charge level in percents + // (or -1 if the battery level is unknown) + int charge_level; + // Set if the temperature is too low + bool low_temperature; + // Set if the temperature is too high + bool high_temperature; +} powerctl_status_t; + +// Gets the current power status. +void powerctl_get_status(powerctl_status_t* status); + +// Enters low-power mode +// +void powerctl_suspend(void); + +#endif // TREZORHAL_POWERCTL_H \ No newline at end of file diff --git a/core/embed/sys/powerctl/inc/sys/wakeup_flags.h b/core/embed/sys/powerctl/inc/sys/wakeup_flags.h new file mode 100644 index 0000000000..1be6ca3c60 --- /dev/null +++ b/core/embed/sys/powerctl/inc/sys/wakeup_flags.h @@ -0,0 +1,40 @@ +/* + * This file is part of the Trezor project, https://trezor.io/ + * + * Copyright (c) SatoshiLabs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef TREZORHAL_WAKEUP_FLAGS_H +#define TREZORHAL_WAKEUP_FLAGS_H + +#include + +// Wakeup flags used to signal the reason of the wakeup +// from the STOP mode + +#define WAKEUP_FLAG_BUTTON 0x01 // Button pressed +#define WAKEUP_FLAG_WPC 0x02 // Wireless power charging event +#define WAKEUP_FLAG_BLE 0x04 // Bluetooth connection event +#define WAKEUP_FLAG_NFC 0x08 // NFC event +#define WAKEUP_FLAG_TIMER 0x10 // Timer event + +// Sets the wakeup flag +void wakeup_flag_set(uint16_t flags); + +// Gets and clears the current wakeup flags +uint16_t wakeup_get_and_clear(void); + +#endif // TREZORHAL_WAKEUP_FLAGS_H diff --git a/core/embed/sys/powerctl/stm32u5/powerctl.c b/core/embed/sys/powerctl/stm32u5/powerctl.c new file mode 100644 index 0000000000..f23666e402 --- /dev/null +++ b/core/embed/sys/powerctl/stm32u5/powerctl.c @@ -0,0 +1,154 @@ +/* + * This file is part of the Trezor project, https://trezor.io/ + * + * Copyright (c) SatoshiLabs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include +#include +#include + +#ifdef USE_TOUCH +#include +#endif + +#ifdef USE_HAPTIC +#include +#endif + +#include "../npm1300/npm1300.h" +#include "../stwlc38/stwlc38.h" + +#ifdef KERNEL_MODE + +// Power control driver state +typedef struct { + // True if the driver is initialized + bool initialized; + +} powerctl_driver_t; + +// Power control driver instance +static powerctl_driver_t g_powerctl_driver = {.initialized = false}; + +bool powerctl_init(void) { + powerctl_driver_t* drv = &g_powerctl_driver; + + if (drv->initialized) { + return true; + } + + // Initialize PMIC + if (!npm1300_init()) { + goto cleanup; + } + + // Initialize wireless charging + if (!stwlc38_init()) { + goto cleanup; + } + + drv->initialized = true; + + return true; + +cleanup: + stwlc38_deinit(); + npm1300_deinit(); + return false; +} + +void powerctl_deinit(void) { + powerctl_driver_t* drv = &g_powerctl_driver; + + if (!drv->initialized) { + return; + } + + stwlc38_deinit(); + npm1300_deinit(); + + drv->initialized = false; +} + +void powerctl_get_status(powerctl_status_t* status) { + powerctl_driver_t* drv = &g_powerctl_driver; + + memset(status, 0, sizeof(powerctl_status_t)); + + if (!drv->initialized) { + return; + } + + // TODO +} + +void powerctl_suspend(void) { + usb_stop(); + +#ifdef USE_HAPTIC + haptic_deinit(); +#endif + +#ifdef USE_TOUCH + touch_deinit(); +#endif + + int backlight_level = display_get_backlight(); + + display_deinit(DISPLAY_RESET_CONTENT); + + HAL_SuspendTick(); + + // Configure PC13 (on-board button) as a wake up pin + EXTI_HandleTypeDef EXTI_Handle = {0}; + EXTI_ConfigTypeDef EXTI_Config = {0}; + EXTI_Config.GPIOSel = EXTI_GPIOC; + EXTI_Config.Line = EXTI_LINE_13; + EXTI_Config.Mode = EXTI_MODE_EVENT; + EXTI_Config.Trigger = EXTI_TRIGGER_RISING; + HAL_EXTI_SetConfigLine(&EXTI_Handle, &EXTI_Config); + // HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN2_HIGH_1); + + // Enter STOP2 mode + HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFE); + + // We get here when the wake-up button is pressed + + // Recover system clock + SystemInit(); + + HAL_ResumeTick(); + + // Initialize drivers + display_init(DISPLAY_RESET_CONTENT); + display_set_backlight(backlight_level); + +#ifdef USE_TOUCH + touch_init(); +#endif + +#ifdef USE_HAPTIC + haptic_init(); +#endif + + usb_start(); +} + +#endif // KERNEL_MODE diff --git a/core/embed/sys/powerctl/wakeup_flags.c b/core/embed/sys/powerctl/wakeup_flags.c new file mode 100644 index 0000000000..1f5717fa46 --- /dev/null +++ b/core/embed/sys/powerctl/wakeup_flags.c @@ -0,0 +1,41 @@ +/* + * This file is part of the Trezor project, https://trezor.io/ + * + * Copyright (c) SatoshiLabs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "wakeup_flags.h" +#include "irq.h" + +#ifdef KERNEL_MODE + +static uint16_t g_wakeup_flags = 0; + +void wakeup_flag_set(uint16_t flags) { + irq_key_t irq_key = irq_lock(); + g_wakeup_flags |= flags; + irq_unlock(irq_key); +} + +uint16_t wakeup_get_and_clear(void) { + irq_key_t irq_key = irq_lock(); + uint16_t flags = g_wakeup_flags; + g_wakeup_flags = 0; + irq_unlock(irq_key); + return flags; +} + +#endif // KERNEL_MODE diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revA.py b/core/site_scons/models/T3W1/trezor_t3w1_revA.py index f0c5460b79..29a7a87023 100644 --- a/core/site_scons/models/T3W1/trezor_t3w1_revA.py +++ b/core/site_scons/models/T3W1/trezor_t3w1_revA.py @@ -119,8 +119,11 @@ def configure( sources += [ "embed/sys/powerctl/npm1300/npm1300.c", - "embed/sys/powerctl/stwlc38/stwlc38.c" + "embed/sys/powerctl/stwlc38/stwlc38.c", + "embed/sys/powerctl/stm32u5/powerctl.c", ] + paths += ["embed/sys/powerctl/inc"] + defines += ["USE_POWERCTL=1"] env.get("ENV")["LINKER_SCRIPT"] = linker_script