123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495 |
- /*
- * Copyright (c) 2019 Actions Semiconductor Co., Ltd
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- /**
- * @file power manager interface
- */
- #if defined(CONFIG_SYS_LOG)
- #define SYS_LOG_NO_NEWLINE
- #ifdef SYS_LOG_DOMAIN
- #undef SYS_LOG_DOMAIN
- #endif
- #define SYS_LOG_DOMAIN "power"
- #endif
- #include <os_common_api.h>
- #include <mem_manager.h>
- #include <msg_manager.h>
- #include <sys_event.h>
- #include <sys_monitor.h>
- #include <property_manager.h>
- #ifndef CONFIG_SIMULATOR
- #include <drivers/power_supply.h>
- #endif
- #ifdef CONFIG_BLUETOOTH
- #include <bt_manager.h>
- #endif
- #ifdef CONFIG_SYS_WAKELOCK
- #include <sys_wakelock.h>
- #endif
- #include <stdlib.h>
- #include <stdio.h>
- #define DEFAULT_BOOTPOWER_LEVEL 3100000
- #define DEFAULT_NOPOWER_LEVEL 3400000
- #define DEFAULT_LOWPOWER_LEVEL 3600000
- #define DEFAULT_REPORT_PERIODS (60*1000)
- struct power_manager_info {
- struct device *dev;
- bat_charge_callback_t cb;
- bat_charge_event_t event;
- bat_charge_event_para_t *para;
- int nopower_level;
- int lowpower_level;
- int current_vol;
- int current_cap;
- int slave_vol;
- int slave_cap;
- int battary_changed;
- uint32_t charge_full_flag;
- uint32_t report_timestamp;
- uint32_t wakelock_flag;
- };
- struct power_manager_info *power_manager = NULL;
- void power_supply_report(bat_charge_event_t event, bat_charge_event_para_t *para)
- {
- struct app_msg msg = {0};
- if (!power_manager) {
- return;
- }
- SYS_LOG_INF("event %d\n", event);
- switch (event) {
- case BAT_CHG_EVENT_DC5V_IN:
- break;
- case BAT_CHG_EVENT_DC5V_OUT:
- break;
- case BAT_CHG_EVENT_CHARGE_START:
- break;
- case BAT_CHG_EVENT_CHARGE_FULL:
- power_manager->charge_full_flag = 1;
- break;
- case BAT_CHG_EVENT_VOLTAGE_CHANGE:
- SYS_LOG_INF("voltage change %u uV\n", para->voltage_val);
- power_manager->current_vol = para->voltage_val;
- break;
- case BAT_CHG_EVENT_CAP_CHANGE:
- SYS_LOG_INF("cap change %u\n", para->cap);
- power_manager->current_cap = para->cap;
- power_manager->battary_changed = 1;
- break;
- case BAT_CHG_EVENT_EXIT_MINI_CHARGE:
- break;
- default:
- break;
- }
- msg.type = MSG_BAT_CHARGE_EVENT;
- msg.cmd = event;
- send_async_msg("main", &msg);
- }
- static int get_system_bat_info(int property)
- {
- union power_supply_propval val;
- int ret;
- if (!power_manager || !power_manager->dev) {
- SYS_LOG_ERR("dev not found\n");
- return -ENODEV;
- }
- ret = power_supply_get_property(power_manager->dev, property, &val);
- if (ret < 0) {
- SYS_LOG_ERR("get property err %d\n", ret);
- return -ENODEV;
- }
- return val.intval;
- }
- static int set_system_bat_info(int property, union power_supply_propval *val)
- {
- if (!power_manager || !power_manager->dev) {
- SYS_LOG_ERR("dev not found\n");
- return -ENODEV;
- }
- power_supply_set_property(power_manager->dev, property, val);
- return 0;
- }
- int power_manager_get_battery_capacity(void)
- {
- #ifdef CONFIG_TWS
- int report_cap = get_system_bat_info(POWER_SUPPLY_PROP_CAPACITY);
- if (bt_manager_tws_get_dev_role() == BTSRV_TWS_MASTER) {
- if (report_cap < power_manager->slave_cap)
- report_cap = power_manager->slave_cap;
- }
- return report_cap;
- #else
- return get_system_bat_info(POWER_SUPPLY_PROP_CAPACITY);
- #endif
- }
- int power_manager_get_battery_capacity_local(void)
- {
- return get_system_bat_info(POWER_SUPPLY_PROP_CAPACITY);
- }
- int power_manager_get_charge_status(void)
- {
- return get_system_bat_info(POWER_SUPPLY_PROP_STATUS);
- }
- int power_manager_get_battery_vol(void)
- {
- return get_system_bat_info(POWER_SUPPLY_PROP_VOLTAGE_NOW);
- }
- int power_manager_get_dc5v_status(void)
- {
- return get_system_bat_info(POWER_SUPPLY_PROP_DC5V);
- }
- int power_manager_get_dc5v_status_chargebox(void)
- {
- return get_system_bat_info(POWER_SUPPLY_PROP_DC5V_STATUS);
- }
- int power_manager_get_dc5v_voltage(void)
- {
- return get_system_bat_info(POWER_SUPPLY_PROP_DC5V_VOLTAGE);
- }
- int power_manger_set_dc5v_pulldown(void)
- {
- return set_system_bat_info(POWER_SUPPLY_SET_DC5V_PULLDOWM, NULL);
- }
- int power_manger_set_init_charge_consume_ma(int consume)
- {
- union power_supply_propval val;
- val.intval = consume;
- SYS_LOG_INF("setting init charge consume ma %d\n", consume);
- return set_system_bat_info(POWER_SUPPLY_SET_CONSUME_MA, &val);
- }
- int power_manger_wake_charger_box(void)
- {
- int ret;
- union power_supply_propval val;
- ret = set_system_bat_info(POWER_SUPPLY_WAKE_CHARGER_BOX, &val);
- if (ret < 0)
- {
- return ret;
- }
- return val.intval;
- }
- int power_manager_set_slave_battery_state(int capacity, int vol)
- {
- power_manager->slave_vol = vol;
- power_manager->slave_cap = capacity;
- power_manager->battary_changed = 1;
- SYS_LOG_INF("vol %dmv cap %d\n", vol, capacity);
- return 0;
- }
- bool power_manager_check_is_no_power(void)
- {
- if (power_manager_get_dc5v_status())
- return false;
- if (power_manager_get_battery_vol() <= power_manager->nopower_level) {
- SYS_LOG_INF("%d %d too low", power_manager_get_battery_vol(), power_manager_get_battery_capacity_local());
- return true;
- }
- return false;
- }
- bool power_manager_check_bat_is_lowpower(void)
- {
- int state = get_system_bat_info(POWER_SUPPLY_PROP_STATUS);
- if(state == POWER_SUPPLY_STATUS_BAT_LOWPOWER)
- return true;
- return false;
- }
- bool power_manager_check_bat_is_full(void)
- {
- int state = get_system_bat_info(POWER_SUPPLY_PROP_STATUS);
- if(state == POWER_SUPPLY_STATUS_FULL)
- return true;
- return false;
- }
- bool power_manager_check_bat_exit(void)
- {
- int state = get_system_bat_info(POWER_SUPPLY_PROP_STATUS);
- if(state == POWER_SUPPLY_STATUS_BAT_NOTEXIST)
- return false;
- return true;
- }
- int power_manager_set_before_poweroff(void)
- {
- if (!power_manager || !power_manager->dev) {
- SYS_LOG_ERR("dev not found\n");
- return -ENODEV;
- }
- power_supply_set_property(power_manager->dev, POWER_SUPPLY_SET_BEFORE_ENTER_S4, NULL);
- return 0;
- }
- int power_manager_sync_slave_battery_state(void)
- {
- uint32_t send_value;
- #ifdef CONFIG_BT_TWS_US281B
- send_value = power_manager->current_cap / 10;
- #else
- send_value = (power_manager->current_cap << 24) | power_manager->current_vol;
- #endif
- #ifdef CONFIG_TWS
- bt_manager_tws_send_event(TWS_BATTERY_EVENT, send_value);
- #endif
- return 0;
- }
- static int _power_manager_work_handle(void)
- {
- if (!power_manager)
- return -ESRCH;
- if (power_manager->battary_changed) {
- power_manager->battary_changed = 0;
- #ifdef CONFIG_BT_HFP_HF
- #ifdef CONFIG_TWS
- if (bt_manager_tws_get_dev_role() == BTSRV_TWS_SLAVE) {
- power_manager_sync_slave_battery_state();
- } else if (bt_manager_tws_get_dev_role() == BTSRV_TWS_MASTER) {
- int report_cap = power_manager->current_cap;
- if (report_cap < power_manager->slave_cap)
- report_cap = power_manager->slave_cap;
-
- bt_manager_hfp_battery_report(BT_BATTERY_REPORT_VAL, report_cap);
- } else {
- bt_manager_hfp_battery_report(BT_BATTERY_REPORT_VAL, power_manager->current_cap);
- }
- #else
- bt_manager_hfp_battery_report(BT_BATTERY_REPORT_VAL, power_manager->current_cap);
- #endif
- #endif
- }
-
- if (power_manager_get_dc5v_status()) {
- if(power_manager->wakelock_flag == 0) {
- #ifdef CONFIG_SYS_WAKELOCK
- sys_wake_lock_ext(PARTIAL_WAKE_LOCK,POWER_WAKE_LOCK_USER);
- #endif
- power_manager->wakelock_flag = 1;
- SYS_LOG_INF("dc5v in, wake lock!");
- }
-
- return 0;
- } else {
- if(power_manager->wakelock_flag != 0) {
- #ifdef CONFIG_SYS_WAKELOCK
- sys_wake_unlock_ext(PARTIAL_WAKE_LOCK,POWER_WAKE_LOCK_USER);
- #endif
- power_manager->wakelock_flag = 0;
- SYS_LOG_INF("dc5v out, wake unlock!");
- }
- }
-
- if (power_manager->charge_full_flag) {
- power_manager->charge_full_flag = 0;
- sys_event_notify(SYS_EVENT_CHARGE_FULL);
- }
- if ((power_manager->current_vol <= power_manager->lowpower_level)
- && ((os_uptime_get_32() - power_manager->report_timestamp) >= DEFAULT_REPORT_PERIODS
- || !power_manager->report_timestamp)) {
- SYS_LOG_INF("%d %d low", power_manager->current_vol, power_manager->lowpower_level);
- #ifdef CONFIG_TWS
- if (bt_manager_tws_get_dev_role() != BTSRV_TWS_SLAVE) {
- sys_event_notify(SYS_EVENT_BATTERY_LOW);
- }
- #else
- sys_event_notify(SYS_EVENT_BATTERY_LOW);
- #endif
- power_manager->report_timestamp = os_uptime_get_32();
- }
- if (power_manager->current_vol <= power_manager->nopower_level) {
- SYS_LOG_INF("%d %d too low", power_manager->current_vol, power_manager->nopower_level);
- sys_event_notify(SYS_EVENT_BATTERY_TOO_LOW);
- return 0;
- }
- return 0;
- }
- int power_manager_save_last_voltage(bool is_clear)
- {
- char temp[6];
- uint16_t bat_vol_saved = power_manager_get_battery_vol()/1000;
- if(is_clear) {
- bat_vol_saved = 0;
- }
- snprintf(temp, sizeof(temp), "%d", bat_vol_saved);
- SYS_LOG_INF("last vol_s: %s", temp);
- #ifdef CONFIG_PROPERTY
- property_set(CFG_BAT_LAST_VOLTAGE, temp, strlen(temp) + 1);
- property_flush(CFG_BAT_LAST_VOLTAGE);
- return 0;
- #else
- return 0;
- #endif
- }
- static int power_supply_set_init_vol(void)
- {
- //uint32_t bat_vol_saved_flag = 0;
- if (!power_manager || !power_manager->dev) {
- SYS_LOG_ERR("dev not found\n");
- return -ENODEV;
- }
- SYS_LOG_INF("%s: %d", __func__, __LINE__);
- #if 0
- soc_pstore_get(SOC_PSTORE_TAG_FLAG_CAP, &bat_vol_saved_flag);
- if(bat_vol_saved_flag != 0) {
- uint32_t bat_vol_saved = 0;
- union power_supply_propval val;
- soc_pstore_get(SOC_PSTORE_TAG_CAPACITY, &bat_vol_saved);
- val.intval = bat_vol_saved;
- power_supply_set_property(power_manager->dev, POWER_SUPPLY_SET_INIT_VOL, &val);
- SYS_LOG_INF("bat init vol from pstore: %dmv\n", bat_vol_saved);
- soc_pstore_set(SOC_PSTORE_TAG_FLAG_CAP, 0);
- }
- #else
- #ifdef CONFIG_PROPERTY
- {
- char temp[8];
- uint16_t bat_vol_saved = 0;
- union power_supply_propval val;
-
- memset(temp, 0, sizeof(temp));
-
- int ret = property_get(CFG_BAT_LAST_VOLTAGE, temp, sizeof(temp));
-
- if (ret >= 0) {
- bat_vol_saved = atoi(temp);
- SYS_LOG_INF("%s, bat_vol: %dmv\n", __func__, bat_vol_saved);
- }
-
- if ((bat_vol_saved > 1000) && (bat_vol_saved < 5000)) {
- val.intval = bat_vol_saved;
- power_supply_set_property(power_manager->dev, POWER_SUPPLY_SET_INIT_VOL, &val);
-
- SYS_LOG_INF("bat init vol from nvram: %dmv\n", bat_vol_saved);
-
- power_manager_save_last_voltage(1);
- }
-
- }
- #endif
- #endif
- return 0;
- }
- static struct power_manager_info global_power_manager;
- int power_manager_init(void)
- {
- power_manager = &global_power_manager;
- memset(power_manager, 0, sizeof(struct power_manager_info));
- power_manager->dev = (struct device *)device_get_binding(CONFIG_ACTS_BATTERY_DEV_NAME);
- if (!power_manager->dev) {
- SYS_LOG_ERR("dev not found\n");
- return -ENODEV;
- }
- #if 0
- if ((power_manager_get_battery_vol() <= DEFAULT_BOOTPOWER_LEVEL)
- && (!power_manager_get_dc5v_status())) {
- SYS_LOG_INF("no power ,shundown: %d\n", power_manager_get_battery_vol());
- sys_pm_poweroff();
- return 0;
- }
- #endif
- power_supply_register_notify(power_manager->dev, power_supply_report);
- power_supply_set_init_vol();
-
- power_supply_enable(power_manager->dev);
-
- #ifdef CONFIG_PROPERTY
- power_manager->lowpower_level = property_get_int(CFG_LOW_POWER_WARNING_LEVEL, DEFAULT_LOWPOWER_LEVEL);
- power_manager->nopower_level = property_get_int(CFG_SHUTDOWN_POWER_LEVEL, DEFAULT_NOPOWER_LEVEL);
- #else
- power_manager->lowpower_level = DEFAULT_LOWPOWER_LEVEL;
- power_manager->nopower_level = DEFAULT_NOPOWER_LEVEL;
- #endif
- power_manager->current_vol = power_manager_get_battery_vol();
- power_manager->current_cap = power_manager_get_battery_capacity_local();
- power_manager->slave_vol = 4200000;
- power_manager->slave_cap = 100;
- power_manager->report_timestamp = 0;
- sys_monitor_add_work(_power_manager_work_handle);
- return 0;
- }
|