Skip to content

Commit 3e02890

Browse files
authored
when switching EPR ports directly (#941)
* when switching EPR ports directly always make sure the charger has exited bypass mode to avoid transients being passed to the system Signed-off-by: Kieran Levin <ktl@frame.work> * handle ACOK threshold Set ACOK threshold when transitioning to NVDC to discharge input power. Make sure charger task is not woken from inside charge_manager task board hook. If this happens the state will be out of sync between charge manager and charger. And charger will try to update with the old values Signed-off-by: Kieran Levin <ktl@frame.work> * force disable the charger bypass when switching Different parts of this run on different threads, so just force bypass off for two runs of the charger updating. Signed-off-by: Kieran Levin <ktl@frame.work> * fix azalea build limit power to 100W when charger not in bypass mode Signed-off-by: Kieran Levin <ktl@frame.work> --------- Signed-off-by: Kieran Levin <ktl@frame.work>
1 parent e7d54ff commit 3e02890

File tree

6 files changed

+124
-36
lines changed

6 files changed

+124
-36
lines changed

driver/charger/isl9241.c

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,8 +1033,22 @@ static enum ec_error_list isl9241_bypass_to_nvdc(int chgnum)
10331033
return rv;
10341034

10351035
/* 12*: Set MaxSysVoltage to full charge. */
1036-
return isl9241_write(chgnum, ISL9241_REG_MAX_SYSTEM_VOLTAGE,
1036+
rv = isl9241_write(chgnum, ISL9241_REG_MAX_SYSTEM_VOLTAGE,
10371037
bi->voltage_max);
1038+
1039+
if (rv)
1040+
return rv;
1041+
1042+
#ifdef CONFIG_CUSTOMIZED_DESIGN
1043+
rv = isl9241_write(chgnum, ISL9241_REG_ACOK_REFERENCE,
1044+
ISL9241_MV_TO_ACOK_REFERENCE(4000));
1045+
#else
1046+
rv = isl9241_write(chgnum, ISL9241_REG_ACOK_REFERENCE,
1047+
ISL9241_MV_TO_ACOK_REFERENCE(
1048+
ISL9241_ACOK_REF_LOW_VOLTAGE_ADAPTER_MV));
1049+
#endif
1050+
1051+
return rv;
10381052
}
10391053

10401054
#ifdef CONFIG_CHARGER_BYPASS_REVERSE_TURBO
@@ -1111,6 +1125,13 @@ static enum ec_error_list isl9241_rtb_chrg_to_rtb(int chgnum)
11111125
}
11121126
#endif
11131127

1128+
static bool isl9241_in_bypass_mode;
1129+
1130+
bool isl9241_is_in_bypass_mode(int chgnum)
1131+
{
1132+
return isl9241_in_bypass_mode;
1133+
}
1134+
11141135
static enum ec_error_list isl9241_enable_bypass_mode(int chgnum, bool enable)
11151136
{
11161137
enum ec_error_list rv = EC_ERROR_UNKNOWN;
@@ -1166,6 +1187,9 @@ static enum ec_error_list isl9241_enable_bypass_mode(int chgnum, bool enable)
11661187
CPRINTS("bypass -> RTB failed(%d)", rv);
11671188
}
11681189
#endif
1190+
if (rv == EC_SUCCESS) {
1191+
isl9241_in_bypass_mode = true;
1192+
}
11691193
return rv;
11701194
}
11711195

@@ -1176,7 +1200,7 @@ static enum ec_error_list isl9241_enable_bypass_mode(int chgnum, bool enable)
11761200

11771201
rv = isl9241_read(chgnum, ISL9241_REG_CONTROL0, &reg);
11781202
if ((reg & ISL9241_CONTROL0_EN_BYPASS_GATE) != ISL9241_CONTROL0_EN_BYPASS_GATE) {
1179-
CPRINTS("Does not in bypass mode, ignore change");
1203+
CPRINTS("Not in bypass mode, ignore change");
11801204
return rv;
11811205
}
11821206

@@ -1198,6 +1222,10 @@ static enum ec_error_list isl9241_enable_bypass_mode(int chgnum, bool enable)
11981222
rv = isl9241_bypass_to_nvdc(chgnum);
11991223
if (rv)
12001224
CPRINTS("bypass -> nvdc failed(%d)", rv);
1225+
1226+
if (rv == EC_SUCCESS) {
1227+
isl9241_in_bypass_mode = false;
1228+
}
12011229
return rv;
12021230
} else {
12031231
/* AC removal */
@@ -1212,11 +1240,23 @@ static enum ec_error_list isl9241_enable_bypass_mode(int chgnum, bool enable)
12121240
if (rv)
12131241
CPRINTS("bypass -> bat failed(%d)", rv);
12141242
}
1243+
1244+
if (rv == EC_SUCCESS) {
1245+
isl9241_in_bypass_mode = false;
1246+
}
1247+
12151248
return rv;
12161249
}
12171250

12181251
return rv;
12191252
}
1253+
#else
1254+
1255+
bool isl9241_is_in_bypass_mode(int chgnum)
1256+
{
1257+
return false;
1258+
}
1259+
12201260
#endif /* CONFIG_CHARGER_BYPASS_MODE */
12211261

12221262
/*****************************************************************************/

include/driver/charger/isl9241_public.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ int isl9241_set_ac_prochot(int chgnum, int ma);
3333
*/
3434
int isl9241_set_dc_prochot(int chgnum, int ma);
3535

36+
/**
37+
* Check if charger is currently in bypass mode
38+
*
39+
* @return true/false
40+
*/
41+
bool isl9241_is_in_bypass_mode(int chgnum);
42+
3643
#ifdef CONFIG_CHARGER_RAA489110
3744
#define ISL9241_AC_PROCHOT_CURRENT_MIN 32 /* mA */
3845
#else /* CONFIG_CHARGER_ISL9241 */

zephyr/program/lotus/include/board_charger.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ int update_charger_in_cutoff_mode(void);
3535
#ifdef CONFIG_BOARD_LOTUS
3636
int charger_in_bypass_mode(void);
3737
void board_charger_lpm_control(int enable);
38+
void board_disable_bypass_oneshot(void);
3839
#endif
3940

4041
#endif /* __CROS_EC_BOARD_CHARGER_H */

zephyr/program/lotus/lotus/src/charger.c

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -344,29 +344,61 @@ DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, charger_update, HOOK_PRIO_DEFAULT);
344344

345345
static bool bypass_force_en;
346346
static bool bypass_force_disable;
347+
348+
static int bypass_force_disable_oneshot;
349+
void board_disable_bypass_oneshot(void)
350+
{
351+
bypass_force_disable_oneshot = 2;
352+
}
347353
__override int board_should_charger_bypass(void)
348354
{
349355
int power_uw = charge_manager_get_power_limit_uw();
350356
int voltage_mv = charge_manager_get_charger_voltage();
351357
int curr_batt = battery_is_present();
358+
int ret;
359+
const char * reason = "";
360+
if (bypass_force_en) {
361+
ret = true;
362+
reason = "forcen";
363+
goto board_exit;
364+
}
352365

353-
if (bypass_force_en)
354-
return true;
366+
if (bypass_force_disable){
367+
ret = false;
368+
reason = "forcedis";
369+
goto board_exit;
370+
}
355371

356-
if (bypass_force_disable)
357-
return false;
372+
if (bypass_force_disable_oneshot) {
373+
bypass_force_disable_oneshot--;
374+
ret = false;
375+
reason = "oneshot";
376+
goto board_exit;
377+
}
358378

359379
if (curr_batt == BP_YES) {
360-
if (power_uw > 100000000)
361-
return true;
362-
else
363-
return false;
380+
if (power_uw > 100000000) {
381+
ret = true;
382+
reason = "power";
383+
goto board_exit;
384+
} else {
385+
ret = false;
386+
goto board_exit;
387+
}
364388
} else {
365-
if (voltage_mv > 20000)
366-
return true;
367-
else
368-
return false;
389+
if (voltage_mv > 20000){
390+
ret = true;
391+
reason = "volt";
392+
goto board_exit;
393+
} else {
394+
ret = false;
395+
goto board_exit;
396+
}
369397
}
398+
board_exit:
399+
/* CPRINTS("board_should_charger_bypass %s %d", reason, ret); */
400+
401+
return ret;
370402
}
371403

372404
int board_want_change_mode(void)
@@ -381,24 +413,6 @@ int board_want_change_mode(void)
381413
return false;
382414
}
383415

384-
int charger_in_bypass_mode(void)
385-
{
386-
int reg;
387-
int rv;
388-
389-
rv = i2c_read16(I2C_PORT_CHARGER, ISL9241_ADDR_FLAGS, ISL9241_REG_CONTROL0, &reg);
390-
391-
/* read register fail */
392-
if (rv)
393-
return 0;
394-
395-
/* charer not enter bypass mode */
396-
if ((reg & ISL9241_CONTROL0_EN_BYPASS_GATE) != ISL9241_CONTROL0_EN_BYPASS_GATE)
397-
return 0;
398-
399-
return 1;
400-
}
401-
402416
int board_discharge_on_ac(int enable)
403417
{
404418
int chgnum;

zephyr/program/lotus/lotus/src/cpu_power.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#include "throttle_ap.h"
2323
#include "util.h"
2424
#include "gpu.h"
25-
25+
#include "driver/charger/isl9241_public.h"
2626

2727
#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args)
2828
#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args)
@@ -992,7 +992,7 @@ void clear_prochot(enum clear_reasons reason)
992992
{
993993
if (events & BIT(PD_PROGRESS_ENTER_EPR_MODE) && (cypd_get_ac_power() > 100000)) {
994994
/* wait charger to entry the bypass mode */
995-
if (charger_in_bypass_mode())
995+
if (isl9241_is_in_bypass_mode(0))
996996
update_pmf_events(BIT(PD_PROGRESS_ENTER_EPR_MODE), 0);
997997
}
998998

@@ -1030,7 +1030,7 @@ void update_soc_power_limit(bool force_update, bool force_no_adapter)
10301030
}
10311031

10321032
#ifdef CONFIG_BOARD_LOTUS
1033-
if (force_update && charger_in_bypass_mode() && !get_gpu_gpio(GPIO_FUNC_ACDC))
1033+
if (force_update && isl9241_is_in_bypass_mode(0) && !get_gpu_gpio(GPIO_FUNC_ACDC))
10341034
set_gpu_gpio(GPIO_FUNC_ACDC, 1);
10351035

10361036
#endif

zephyr/program/lotus/src/cypress_pd_common.c

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#ifdef CONFIG_BOARD_LOTUS
3434
#include "gpu.h"
3535
#include "cpu_power.h"
36+
#include "board_charger.h"
3637
#endif
3738

3839
#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args)
@@ -467,7 +468,7 @@ void exit_epr_mode(void)
467468
CCG_PD_CONTROL_REG(port_idx & 0x1),
468469
CCG_PD_CMD_INITIATE_EPR_EXIT);
469470

470-
hook_call_deferred(&epr_flow_pending_deferred_data, 500 * MSEC);
471+
hook_call_deferred(&epr_flow_pending_deferred_data, 1000 * MSEC);
471472
}
472473
}
473474
}
@@ -1328,6 +1329,8 @@ static void cypd_update_port_state(int controller, int port)
13281329
pd_epr_in_progress &= ~EPR_PROCESS_MASK;
13291330
}
13301331
#endif
1332+
1333+
charge_wakeup();
13311334
}
13321335

13331336
int cypd_set_power_state(int power_state, int controller)
@@ -1679,6 +1682,11 @@ int cypd_get_ac_power(void)
16791682
ac_power_mW = (pd_port_states[prev_charge_port].current
16801683
* pd_port_states[prev_charge_port].voltage);
16811684

1685+
if (!isl9241_is_in_bypass_mode(0)) {
1686+
/* limit to 100W if not in bypass mode */
1687+
ac_power_mW = MIN(100000000, ac_power_mW);
1688+
}
1689+
16821690
return (ac_power_mW / 1000);
16831691
}
16841692

@@ -2173,12 +2181,16 @@ int board_set_active_charge_port(int charge_port)
21732181
int i;
21742182
CPRINTS("%s port %d, prev:%d", __func__, charge_port, prev_charge_port);
21752183

2184+
21762185
if (prev_charge_port == charge_port) {
21772186
/* in the case of hard reset, we do not turn off the old
21782187
* port, but the PD will implicitly clear the port
21792188
* so we need to turn on the vbus control again.
21802189
*/
21812190
cypd_cfet_vbus_control(charge_port, true, true);
2191+
#ifdef CONFIG_BOARD_LOTUS
2192+
board_disable_bypass_oneshot();
2193+
#endif
21822194
return EC_SUCCESS;
21832195
}
21842196

@@ -2187,6 +2199,20 @@ int board_set_active_charge_port(int charge_port)
21872199
prev_charge_port != charge_port) {
21882200
/* Turn off the previous charge port before turning on the next port */
21892201
cypd_cfet_vbus_control(prev_charge_port, false, true);
2202+
#ifdef CONFIG_BOARD_LOTUS
2203+
board_disable_bypass_oneshot();
2204+
#endif
2205+
if (isl9241_is_in_bypass_mode(0)) {
2206+
CPRINTS("Force exit bypass mode for port switch");
2207+
if (chg_chips[0].drv->enable_bypass_mode)
2208+
chg_chips[0].drv->enable_bypass_mode(0, false);
2209+
/* ACOK threshold has been lowered, give the charger some time to
2210+
* discharge the input caps before switching to the new port
2211+
*/
2212+
usleep(8*MSEC);
2213+
}
2214+
2215+
21902216
}
21912217

21922218
for (i = 0; i < PD_PORT_COUNT; i++) {

0 commit comments

Comments
 (0)