@@ -91,6 +91,7 @@ static int manual_current; /* Manual current override (-1 = no override) */
91
91
static unsigned int user_current_limit = -1U ;
92
92
test_export_static timestamp_t shutdown_target_time ;
93
93
static timestamp_t precharge_start_time ;
94
+ static struct sustain_soc sustain_soc ;
94
95
95
96
/*
96
97
* The timestamp when the battery charging current becomes stable.
@@ -1155,6 +1156,8 @@ static void dump_charge_state(void)
1155
1156
battery_seems_to_be_disconnected );
1156
1157
ccprintf ("battery_was_removed = %d\n" , battery_was_removed );
1157
1158
ccprintf ("debug output = %s\n" , debugging ? "on" : "off" );
1159
+ ccprintf ("sustain charge = %d%% ~ %d%%\n" ,
1160
+ sustain_soc .lower , sustain_soc .upper );
1158
1161
#undef DUMP
1159
1162
}
1160
1163
@@ -1630,6 +1633,43 @@ static int battery_outside_charging_temperature(void)
1630
1633
}
1631
1634
#endif
1632
1635
1636
+ static void sustain_soc_disable (void )
1637
+ {
1638
+ sustain_soc .lower = -1 ;
1639
+ sustain_soc .upper = -1 ;
1640
+ }
1641
+
1642
+ static int sustain_soc_set (int16_t lower , int16_t upper )
1643
+ {
1644
+ if (sustain_soc .lower < sustain_soc .upper
1645
+ && 0 <= sustain_soc .lower && sustain_soc .upper <= 100 ) {
1646
+ sustain_soc .lower = lower ;
1647
+ sustain_soc .upper = upper ;
1648
+ return EC_SUCCESS ;
1649
+ }
1650
+
1651
+ CPRINTS ("Invalid param: %s(%d, %d)" , __func__ , lower , upper );
1652
+ return EC_ERROR_INVAL ;
1653
+ }
1654
+
1655
+ static bool sustain_soc_enabled (void )
1656
+ {
1657
+ return sustain_soc .lower != -1 && sustain_soc .upper != -1 ;
1658
+ }
1659
+
1660
+ static void sustain_battery_soc (void )
1661
+ {
1662
+ /* If both of AC and battery aren't present, nothing to do. */
1663
+ if (!curr .ac || curr .batt .is_present != BP_YES
1664
+ || !sustain_soc_enabled ())
1665
+ return ;
1666
+
1667
+ if (curr .batt .state_of_charge < sustain_soc .lower )
1668
+ set_chg_ctrl_mode (CHARGE_CONTROL_NORMAL );
1669
+ else if (sustain_soc .upper < curr .batt .state_of_charge )
1670
+ set_chg_ctrl_mode (CHARGE_CONTROL_DISCHARGE );
1671
+ }
1672
+
1633
1673
/*****************************************************************************/
1634
1674
/* Hooks */
1635
1675
void charger_init (void )
@@ -1645,6 +1685,8 @@ void charger_init(void)
1645
1685
* their tasks. Make them ready first.
1646
1686
*/
1647
1687
battery_get_params (& curr .batt );
1688
+
1689
+ sustain_soc_disable ();
1648
1690
}
1649
1691
DECLARE_HOOK (HOOK_INIT , charger_init , HOOK_PRIO_DEFAULT );
1650
1692
@@ -2061,6 +2103,7 @@ void charger_task(void *u)
2061
2103
(is_full != prev_full ) ||
2062
2104
(curr .state != prev_state ) ||
2063
2105
(curr .batt .display_charge != prev_disp_charge )) {
2106
+ sustain_battery_soc ();
2064
2107
show_charging_progress ();
2065
2108
prev_charge = curr .batt .state_of_charge ;
2066
2109
prev_disp_charge = curr .batt .display_charge ;
@@ -2621,6 +2664,22 @@ charge_command_charge_control(struct host_cmd_handler_args *args)
2621
2664
if (rv != EC_SUCCESS )
2622
2665
return EC_RES_ERROR ;
2623
2666
2667
+ if (args -> version >= 2 ) {
2668
+ /*
2669
+ * If charge mode is explicitly set (e.g. DISCHARGE), make sure
2670
+ * sustain charge is disabled. To go back to normal mode (and
2671
+ * disable sustain charge), set mode=NORMAL, lower=-1, upper=-1.
2672
+ */
2673
+ if (chg_ctl_mode == CHARGE_CONTROL_NORMAL ) {
2674
+ rv = sustain_soc_set (p -> sustain_charge .lower ,
2675
+ p -> sustain_charge .upper );
2676
+ if (rv )
2677
+ return EC_RES_INVALID_PARAM ;
2678
+ } else {
2679
+ sustain_soc_disable ();
2680
+ }
2681
+ }
2682
+
2624
2683
#ifdef CONFIG_CHARGER_DISCHARGE_ON_AC
2625
2684
#ifdef CONFIG_CHARGER_DISCHARGE_ON_AC_CUSTOM
2626
2685
rv = board_discharge_on_ac (p -> mode == CHARGE_CONTROL_DISCHARGE );
@@ -2824,6 +2883,7 @@ static int command_chgstate(int argc, char **argv)
2824
2883
{
2825
2884
int rv ;
2826
2885
int val ;
2886
+ char * e ;
2827
2887
2828
2888
if (argc > 1 ) {
2829
2889
if (!strcasecmp (argv [1 ], "idle" )) {
@@ -2858,6 +2918,20 @@ static int command_chgstate(int argc, char **argv)
2858
2918
return EC_ERROR_PARAM_COUNT ;
2859
2919
if (!parse_bool (argv [2 ], & debugging ))
2860
2920
return EC_ERROR_PARAM2 ;
2921
+ } else if (!strcasecmp (argv [1 ], "sustain" )) {
2922
+ int lower , upper ;
2923
+
2924
+ if (argc <= 3 )
2925
+ return EC_ERROR_PARAM_COUNT ;
2926
+ lower = strtoi (argv [2 ], & e , 0 );
2927
+ if (* e )
2928
+ return EC_ERROR_PARAM2 ;
2929
+ upper = strtoi (argv [3 ], & e , 0 );
2930
+ if (* e )
2931
+ return EC_ERROR_PARAM3 ;
2932
+ rv = sustain_soc_set (lower , upper );
2933
+ if (rv )
2934
+ return EC_ERROR_INVAL ;
2861
2935
} else {
2862
2936
return EC_ERROR_PARAM1 ;
2863
2937
}
@@ -2867,7 +2941,8 @@ static int command_chgstate(int argc, char **argv)
2867
2941
return EC_SUCCESS ;
2868
2942
}
2869
2943
DECLARE_CONSOLE_COMMAND (chgstate , command_chgstate ,
2870
- "[idle|discharge|debug on|off]" ,
2944
+ "[idle|discharge|debug on|off]"
2945
+ "\n[sustain lower upper]" ,
2871
2946
"Get/set charge state machine status" );
2872
2947
2873
2948
#ifdef CONFIG_EC_EC_COMM_BATTERY_MASTER
0 commit comments