summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Chao <scott_chao@wistron.corp-partner.google.com>2021-08-16 11:00:21 +0800
committerCommit Bot <commit-bot@chromium.org>2021-10-01 21:23:59 +0000
commitf5ba5ec8361d7dadefb3860a05bf80e4ad230a44 (patch)
treecf094b2d197e40bca8dad511f55940081ced04b1
parent36986a9efbd475c249d4045573b20f9d1a8ba2f1 (diff)
downloadchrome-ec-f5ba5ec8361d7dadefb3860a05bf80e4ad230a44.tar.gz
primus: control prochot
BUG=b:198722634 BRANCH=none TEST=make -j BOARD=primus TEST=verified by power team Signed-off-by: Scott Chao <scott_chao@wistron.corp-partner.google.com> Change-Id: I777f803b91f0449317f0185a6ca77348de3835bc Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3096806 Reviewed-by: caveh jalali <caveh@chromium.org> Commit-Queue: caveh jalali <caveh@chromium.org>
-rw-r--r--board/primus/board.h1
-rw-r--r--board/primus/build.mk3
-rw-r--r--board/primus/ec.tasklist1
-rw-r--r--board/primus/prochot.c209
-rw-r--r--board/primus/sensors.c7
5 files changed, 220 insertions, 1 deletions
diff --git a/board/primus/board.h b/board/primus/board.h
index 96562ec7a4..dc16251b93 100644
--- a/board/primus/board.h
+++ b/board/primus/board.h
@@ -159,6 +159,7 @@ enum adc_channel {
ADC_TEMP_SENSOR_3_CHARGER,
ADC_TEMP_SENSOR_4_MEMORY,
ADC_TEMP_SENSOR_5_USBC,
+ ADC_IADPT,
ADC_CH_COUNT
};
diff --git a/board/primus/build.mk b/board/primus/build.mk
index d6fe9b4808..9dab971565 100644
--- a/board/primus/build.mk
+++ b/board/primus/build.mk
@@ -20,7 +20,8 @@ board-y+=fw_config.o
board-y+=i2c.o
board-y+=keyboard.o
board-y+=led.o
-board-y+=pwm.o
+board-y+=prochot.o
board-y+=ps2.o
+board-y+=pwm.o
board-y+=sensors.o
board-y+=usbc_config.o
diff --git a/board/primus/ec.tasklist b/board/primus/ec.tasklist
index c0a5194e89..83415ffceb 100644
--- a/board/primus/ec.tasklist
+++ b/board/primus/ec.tasklist
@@ -26,4 +26,5 @@
TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \
TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, TASK_STACK_SIZE) \
TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, TASK_STACK_SIZE) \
+ TASK_NOTEST(PROCHOT, prochot_task, NULL, LARGER_TASK_STACK_SIZE) \
TASK_NOTEST(LOGOLED, logoled_task, NULL, LARGER_TASK_STACK_SIZE)
diff --git a/board/primus/prochot.c b/board/primus/prochot.c
new file mode 100644
index 0000000000..335e2708e4
--- /dev/null
+++ b/board/primus/prochot.c
@@ -0,0 +1,209 @@
+/* Copyright 2021 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "adc.h"
+#include "battery.h"
+#include "battery_smart.h"
+#include "charge_manager.h"
+#include "charger.h"
+#include "console.h"
+#include "driver/charger/bq25710.h"
+#include "hooks.h"
+#include "i2c.h"
+#include "math_util.h"
+#include "task.h"
+
+/* Console output macros */
+#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args)
+
+#define ADT_RATING_W (PD_MAX_POWER_MW / 1000)
+#define BATT_MAX_CONTINUE_DISCHARGE_WATT 66
+#define PROCHOT_EVENT_200MS_TICK TASK_EVENT_CUSTOM_BIT(0)
+
+struct batt_para {
+ int battery_continuous_discharge_mw;
+ int battery_design_mWh;
+ int flags;
+ int state_of_charge;
+};
+
+static struct batt_para batt_params;
+
+static int cal_sys_watt(void)
+{
+ int Vacpacn;
+ int V_iadpt;
+ int IDPM;
+ int W_adpt;
+
+ /* Read ADC_IADPT from BQ25720 */
+ V_iadpt = adc_read_channel(ADC_IADPT);
+
+ /* Calculate V(ACP-ACN)
+ * We select IADPT_FAIN as 40 for more precise
+ */
+ Vacpacn = V_iadpt * 1000 / 40;
+
+ /* Calculate the input current */
+ IDPM = Vacpacn / CONFIG_CHARGER_SENSE_RESISTOR_AC;
+
+ /* Current multiplied by 20v to calculate actual adapter wattage */
+ W_adpt = IDPM * 20 / 97 * 100;
+
+ return W_adpt;
+}
+
+static int get_batt_parameter(void)
+{
+ int battery_voltage_mv;
+ int battery_current_ma;
+ int battery_design_voltage_mv;
+ int battery_design_capacity_mAh;
+ int rv = 0;
+
+ batt_params.flags = 0;
+
+ if (sb_read(SB_VOLTAGE, &battery_voltage_mv))
+ batt_params.flags |= BATT_FLAG_BAD_VOLTAGE;
+
+ /* Battery_current sometimes return a very huge number
+ * and cause prochot keep toggling so add (int16_t) to guard it.
+ */
+ if (sb_read(SB_CURRENT, &battery_current_ma))
+ batt_params.flags |= BATT_FLAG_BAD_CURRENT;
+ else
+ battery_current_ma = (int16_t)battery_current_ma;
+
+ /* calculate battery wattage and convert to mW */
+ batt_params.battery_continuous_discharge_mw =
+ (battery_voltage_mv * battery_current_ma) / 1000;
+
+ rv |= sb_read(SB_DESIGN_VOLTAGE, &battery_design_voltage_mv);
+ rv |= sb_read(SB_DESIGN_CAPACITY, &battery_design_capacity_mAh);
+ batt_params.battery_design_mWh = (battery_design_voltage_mv *
+ battery_design_capacity_mAh) / 1000;
+
+ if (sb_read(SB_RELATIVE_STATE_OF_CHARGE, &batt_params.state_of_charge))
+ batt_params.flags |= BATT_FLAG_BAD_STATE_OF_CHARGE;
+
+ return (batt_params.flags || rv);
+}
+
+static int get_chg_watt(void)
+{
+ int adapter_current_ma;
+ int adapter_voltage_mv;
+ int adapter_wattage;
+
+ adapter_current_ma = charge_manager_get_charger_current();
+ adapter_voltage_mv = charge_manager_get_charger_voltage();
+ adapter_wattage = adapter_current_ma * adapter_voltage_mv / 1000 / 1000;
+
+ return adapter_wattage;
+}
+
+static void assert_prochot(void)
+{
+ int adapter_wattage;
+ int adpt_mw;
+ int reg;
+ int total_W;
+
+ /* no AC, don't assert PROCHOT */
+ if (!extpower_is_present()) {
+ gpio_set_level(GPIO_EC_PROCHOT_ODL, 1);
+ return;
+ }
+
+ /* Set 0x12 bit4=1 */
+ if (charger_get_option(&reg))
+ CPRINTS("Failed to read bq25720");
+ else {
+ /* only execute if get_option succeeded. */
+ reg |= BQ25710_CHARGE_OPTION_0_IADP_GAIN;
+ if (charger_set_option(reg))
+ return;
+ }
+
+ /* Calculate actual system W */
+ adpt_mw = cal_sys_watt();
+
+ /* Read battery info
+ * if any flag is set, skip this cycle and hope
+ * the next cycle succeeds
+ */
+ if (get_batt_parameter())
+ return;
+
+ /* When battery is discharging, the battery current will be negative */
+ if (batt_params.battery_continuous_discharge_mw < 0) {
+ total_W = adpt_mw +
+ ABS(batt_params.battery_continuous_discharge_mw);
+ } else {
+ /* we won't assert prochot when battery is charging. */
+ total_W = adpt_mw;
+ }
+ total_W /= 1000;
+
+ /* Get adapter wattage */
+ adapter_wattage = get_chg_watt();
+
+ if (adapter_wattage < ADT_RATING_W) {
+ /* if adapter < 60W */
+ /* if no battery or battery < 10% */
+ if (!battery_hw_present() ||
+ batt_params.state_of_charge <= 10) {
+ if (total_W > (adapter_wattage * 105/100))
+ gpio_set_level(GPIO_EC_PROCHOT_ODL, 0);
+ else if (total_W < (adapter_wattage * 90/100))
+ gpio_set_level(GPIO_EC_PROCHOT_ODL, 1);
+ } else {
+ /* AC + battery */
+ if (total_W > (adapter_wattage +
+ BATT_MAX_CONTINUE_DISCHARGE_WATT))
+ gpio_set_level(GPIO_EC_PROCHOT_ODL, 0);
+ else if (total_W < (adapter_wattage +
+ (BATT_MAX_CONTINUE_DISCHARGE_WATT *
+ 90/100)))
+ gpio_set_level(GPIO_EC_PROCHOT_ODL, 1);
+ }
+ } else {
+ /* if adapter = 60W */
+ /* if no battery or battery < 10% */
+ if (!battery_hw_present() ||
+ batt_params.state_of_charge <= 10) {
+ if (total_W > (ADT_RATING_W * 105/100))
+ gpio_set_level(GPIO_EC_PROCHOT_ODL, 0);
+ else if (total_W <= ADT_RATING_W)
+ gpio_set_level(GPIO_EC_PROCHOT_ODL, 1);
+ } else {
+ /* AC + battery */
+ if (total_W > (ADT_RATING_W +
+ BATT_MAX_CONTINUE_DISCHARGE_WATT))
+ gpio_set_level(GPIO_EC_PROCHOT_ODL, 0);
+ else if (total_W < (ADT_RATING_W +
+ BATT_MAX_CONTINUE_DISCHARGE_WATT) * 95/100)
+ gpio_set_level(GPIO_EC_PROCHOT_ODL, 1);
+ }
+ }
+}
+
+/* Called by hook task every 200 ms */
+static void control_prochot_tick(void)
+{
+ task_set_event(TASK_ID_PROCHOT, PROCHOT_EVENT_200MS_TICK);
+}
+DECLARE_HOOK(HOOK_TICK, control_prochot_tick, HOOK_PRIO_DEFAULT);
+
+void prochot_task(void *u)
+{
+ uint32_t evt;
+
+ while (1) {
+ evt = task_wait_event(-1);
+
+ if (evt & PROCHOT_EVENT_200MS_TICK)
+ assert_prochot();
+ }
+}
diff --git a/board/primus/sensors.c b/board/primus/sensors.c
index 33ea302a2a..d297912772 100644
--- a/board/primus/sensors.c
+++ b/board/primus/sensors.c
@@ -47,6 +47,13 @@ const struct adc_t adc_channels[] = {
.factor_div = ADC_READ_MAX + 1,
.shift = 0,
},
+ [ADC_IADPT] = {
+ .name = "CHARGER_IADPT",
+ .input_ch = NPCX_ADC_CH3,
+ .factor_mul = ADC_MAX_VOLT,
+ .factor_div = ADC_READ_MAX + 1,
+ .shift = 0,
+ },
};
BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT);