/*---------------------------------------------------------------------------- * Copyright (c) TJD Technologies Co., Ltd. 2025. All rights reserved. * * Description: common_pm.c * * Author: luziquan@ss-tjd.com * * Create: 2024-05-29 *--------------------------------------------------------------------------*/ #include "common_pm.h" #include "common_pm_port.h" #include "gpio.h" #include "i2c_porting.h" #include "osal_list.h" #include "pinctrl.h" #include "sys_config.h" #include "uart.h" #include #include // clang-format off #define ENABLE_PRINT_INFO 1 #define DEBUG_ENABLE 0 #if ENABLE_PRINT_INFO #define static_print_info(...) sys_pm_log_i(__VA_ARGS__) // 一般信息打印宏控制 #define static_print_warn(...) sys_pm_log_w(__VA_ARGS__) // 警告信息打印一般常开 #define static_print_error(...) sys_pm_log_e(__VA_ARGS__) // 错误信息打印一般常开 #if DEBUG_ENABLE #define static_print_debug(...) sys_pm_log_d(__VA_ARGS__) #else #define static_print_debug(...) #endif #else #define static_print_info(...) #define static_print_warn(...) #define static_print_error(...) #endif // clang-format on #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #endif typedef struct { struct osal_list_head node; screen_event_callback callback; } screen_event_node_t; typedef struct { struct osal_list_head node; shutdown_event_callback callback; } shutdown_event_node_t; typedef struct { struct osal_list_head node; recover_event_callback callback; } recover_event_node_t; /* 相同的gpio放在一起,避免重复设置 */ // clang-format off static power_manager_device_t g_model_device[POWER_MODEL_MAX_ID] = { // [POWER_MODEL_SCREEN_ID] = {NORMAL_LDO_GPIO_PIN, NULL, PM_POWER_STATUS_OFF}, // [POWER_MODEL_ENCODER_ID] = {NORMAL_LDO_GPIO_PIN, NULL, PM_POWER_STATUS_OFF}, [POWER_MODEL_GPS_ID] = {GPS_POWER_GPIO_PIN, NULL, PM_POWER_STATUS_OFF}, [POWER_MODEL_HRSENSOR_ID] = {HR_LDO_GPIO_PIN, NULL, PM_POWER_STATUS_OFF}, [POWER_MODEL_ALIPAY_ID] = {ALIPAY_LDO_GPIO_PIN, NULL, PM_POWER_STATUS_OFF}, }; // clang-format on static bool g_power_manager_inited = false; static OSAL_LIST_HEAD(g_screen_event_list); static OSAL_LIST_HEAD(g_shutdown_event_list); static OSAL_LIST_HEAD(g_recover_event_list); static void open(void) { if (g_power_manager_inited == true) { static_print_error("power_manager has been opened"); return; } power_manager_gpio_init(); power_manager_gpio_set_dir(NORMAL_LDO_GPIO_PIN, GPIO_OUTPUT); power_manager_gpio_set(NORMAL_LDO_GPIO_PIN, PM_POWER_STATUS_OFF); power_manager_gpio_set(NORMAL_LDO_GPIO_PIN, PM_POWER_STATUS_ON); for (uint8_t i = 0; i < ARRAY_SIZE(g_model_device); i++) { if (i != 0 && g_model_device[i].ldo_gpio == g_model_device[i - 1].ldo_gpio) { continue; } power_manager_gpio_set_dir(g_model_device[i].ldo_gpio, GPIO_OUTPUT); power_manager_gpio_set(g_model_device[i].ldo_gpio, g_model_device[i].status); } g_power_manager_inited = true; static_print_info("power_manager open suceess"); } static void close(void) { g_power_manager_inited = false; static_print_info("power_manager close suceess"); } static uint32_t set_model_power_on(const power_model_id_t model_id) { // 有一个Model需要开启,就开启 g_model_device[model_id].status = power_manager_gpio_set(g_model_device[model_id].ldo_gpio, PM_POWER_STATUS_ON); return POWER_MANAGER_SUCC; } static uint32_t set_model_power_off(const power_model_id_t model_id) { // 全部Model都需要关闭,才关闭 for (int i = 0; i < POWER_MODEL_MAX_ID; i++) { if (i == model_id) { continue; } /* 对相同发的gpio做判断 */ if (g_model_device[i].ldo_gpio == g_model_device[model_id].ldo_gpio && g_model_device[i].status == PM_POWER_STATUS_ON) { g_model_device[model_id].status = PM_POWER_STATUS_OFF; return POWER_MANAGER_ARBITRA_FAIL; } } static_print_debug("Arbitration Succ Close"); g_model_device[model_id].status = power_manager_gpio_set(g_model_device[model_id].ldo_gpio, PM_POWER_STATUS_OFF); return POWER_MANAGER_SUCC; } static uint32_t set_model_power_status(const power_model_id_t model_id, const power_status_t status) { static_print_debug("power_manager set model_id = %d, status = %d", model_id, status); if (g_power_manager_inited == false || model_id >= POWER_MODEL_MAX_ID) { return POWER_MANAGER_FAIL; } if (g_model_device[model_id].status == status) { return status; } if (g_model_device[model_id].ldo_gpio == 0) { static_print_error("model %d gpio is invalid", model_id); return POWER_MANAGER_FAIL; } switch (status) { case PM_POWER_STATUS_ON: return set_model_power_on(model_id); case PM_POWER_STATUS_OFF: return set_model_power_off(model_id); default: return POWER_MANAGER_FAIL; } } static uint32_t get_model_power_status(const power_model_id_t model_id) { if (g_power_manager_inited == false || model_id >= POWER_MODEL_MAX_ID) { return POWER_MANAGER_FAIL; } return g_model_device[model_id].status; } static void master_power_off(void) { power_manager_gpio_set(MASTER_DCDC_GPIO_PIN, PM_POWER_STATUS_OFF); } static uint32_t register_lp_event(const power_model_id_t model_id, lp_event_callback callback) { if (g_power_manager_inited == false || model_id >= POWER_MODEL_MAX_ID) { return POWER_MANAGER_FAIL; } if (g_model_device[model_id].lp_callback != NULL) { return POWER_MANAGER_FAIL; } g_model_device[model_id].lp_callback = callback; static_print_debug("register lp event model_id = %d", model_id); return POWER_MANAGER_SUCC; } static uint32_t unregister_lp_event(const power_model_id_t model_id) { if (g_power_manager_inited == false || model_id >= POWER_MODEL_MAX_ID) { return POWER_MANAGER_FAIL; } if (g_model_device[model_id].lp_callback == NULL) { return POWER_MANAGER_FAIL; } g_model_device[model_id].lp_callback = NULL; return POWER_MANAGER_SUCC; } static uint32_t register_screen_event(screen_event_callback callback) { screen_event_node_t *new_node = (screen_event_node_t *)malloc(sizeof(screen_event_node_t)); if (new_node == NULL) { return POWER_MANAGER_FAIL; } new_node->callback = callback; osal_list_add_tail(&new_node->node, &g_screen_event_list); return POWER_MANAGER_SUCC; } static uint32_t unregister_screen_event(screen_event_callback callback) { struct osal_list_head *cur = NULL; struct osal_list_head *next = NULL; if (callback == NULL) { static_print_error("parameter invalid!"); return POWER_MANAGER_FAIL; } if (osal_list_empty(&g_screen_event_list) != 0) { static_print_error("g_screen_event_list is empty!"); return POWER_MANAGER_FAIL; } osal_list_for_each_safe(cur, next, &g_screen_event_list) { screen_event_node_t *node = osal_list_entry(cur, screen_event_node_t, node); if (node->callback == callback) { osal_list_del(cur); free(node); return POWER_MANAGER_SUCC; } } return POWER_MANAGER_FAIL; } static uint32_t register_shutdown_callback(shutdown_event_callback callback) { shutdown_event_node_t *new_node = (shutdown_event_node_t *)malloc(sizeof(shutdown_event_node_t)); if (new_node == NULL) { return POWER_MANAGER_FAIL; } new_node->callback = callback; osal_list_add_tail(&new_node->node, &g_shutdown_event_list); return POWER_MANAGER_SUCC; } static uint32_t unregister_shutdown_callback(shutdown_event_callback callback) { struct osal_list_head *cur = NULL; struct osal_list_head *next = NULL; if (callback == NULL) { static_print_error("parameter invalid!"); return POWER_MANAGER_FAIL; } if (osal_list_empty(&g_shutdown_event_list) != 0) { static_print_error("g_shutdown_event_list is empty!"); return POWER_MANAGER_FAIL; } osal_list_for_each_safe(cur, next, &g_shutdown_event_list) { shutdown_event_node_t *node = osal_list_entry(cur, shutdown_event_node_t, node); if (node->callback == callback) { osal_list_del(cur); free(node); return POWER_MANAGER_SUCC; } } return POWER_MANAGER_FAIL; } static uint32_t register_recover_callback(recover_event_callback callback) { recover_event_node_t *new_node = (recover_event_node_t *)malloc(sizeof(recover_event_node_t)); if (new_node == NULL) { return POWER_MANAGER_FAIL; } new_node->callback = callback; osal_list_add_tail(&new_node->node, &g_recover_event_list); return POWER_MANAGER_SUCC; } static uint32_t unregister_recover_callback(recover_event_callback callback) { struct osal_list_head *cur = NULL; struct osal_list_head *next = NULL; if (callback == NULL) { static_print_error("parameter invalid!"); return POWER_MANAGER_FAIL; } if (osal_list_empty(&g_recover_event_list) != 0) { static_print_error("g_recover_event_list is empty!"); return POWER_MANAGER_FAIL; } osal_list_for_each_safe(cur, next, &g_recover_event_list) { recover_event_node_t *node = osal_list_entry(cur, recover_event_node_t, node); if (node->callback == callback) { osal_list_del(cur); free(node); return POWER_MANAGER_SUCC; } } return POWER_MANAGER_FAIL; } static struct power_manager_class_ops g_power_manager_ops = { .open = open, .close = close, .get_model_power_status = get_model_power_status, .set_model_power_status = set_model_power_status, .register_lp_on_event = register_lp_event, .unregister_lp_on_event = unregister_lp_event, .register_screen_on_event = register_screen_event, .unregister_screen_on_event = unregister_screen_event, .register_shutdown_event = register_shutdown_callback, .unregister_shutdown_event = unregister_shutdown_callback, .register_recover_event = register_recover_callback, .unregister_recover_event = unregister_recover_callback, }; const struct power_manager_class_ops *tjd_driver_common_pm_get_ops(void) { return &g_power_manager_ops; } void tjd_driver_pm_lp_enter(pm_event_t event) { if (event == PM_EVENT_SUSPEND) { /* 心率,马达,加速计外设的I2C通道寄存器保存,关中断 */ /* 进入低功耗模式 */ for (uint8_t i = 0; i < ARRAY_SIZE(g_model_device); i++) { if (g_model_device[i].lp_callback != NULL) { g_model_device[i].lp_callback(PM_EVENT_SUSPEND); } } // gsensor 加密se i2c0 i2c_save_reg(I2C_BUS_0); // encoder hr i2c2 msensor i2c_save_reg(I2C_BUS_2); } else { /* 心率,马达,加速计外设的I2C通道寄存器的恢复,关中断,重新配置pinmux,重新初始化。 */ /* 退出低功耗模式 */ i2c_recovery_reg(I2C_BUS_0); i2c_recovery_reg(I2C_BUS_2); for (uint8_t i = 0; i < ARRAY_SIZE(g_model_device); i++) { if (g_model_device[i].lp_callback != NULL) { g_model_device[i].lp_callback(PM_EVENT_RESUME); } } } } void tjd_driver_pm_screen_event(screen_status_t status) { screen_event_node_t *inst = NULL; osal_list_for_each_entry(inst, &g_screen_event_list, node) { if (inst != NULL) { inst->callback(status); } } } void tjd_driver_pm_power_down_event(void) { static_print_debug("power_manager shutdown process"); for (uint8_t i = 0; i < ARRAY_SIZE(g_model_device); i++) { power_manager_gpio_set(g_model_device[i].ldo_gpio, PM_POWER_STATUS_OFF); } master_power_off(); } void tjd_driver_pm_shutdown_event(void) { shutdown_event_node_t *inst = NULL; osal_list_for_each_entry(inst, &g_shutdown_event_list, node) { if (inst != NULL) { inst->callback(); } } } void tjd_driver_pm_recover_event(void) { recover_event_node_t *inst = NULL; osal_list_for_each_entry(inst, &g_recover_event_list, node) { if (inst != NULL) { inst->callback(); } } }