summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Wang <matt_wang@compal.corp-partner.google.com>2022-03-14 19:52:30 +0800
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-05-06 09:35:12 +0000
commit52b10fc3261a28a5debae0f0e772bb67b3aee3b1 (patch)
tree4670eb1c9160130edd29df9c1e2e4615e9738a4e
parent07b9ef58975373fc04810439a43dd383750ce252 (diff)
downloadchrome-ec-52b10fc3261a28a5debae0f0e772bb67b3aee3b1.tar.gz
kinox: implement OBP function
Add the two ADC pins to detect the ADP_ID and the PWR_IN_IMON. ADP_ID can identify the Barrel power device and the PWR_IN_IMON can detect the adapter input voltage. Use those ADC values to set the OBP pointer then trigger PROCHOT. BUG=b:211806236;b:213955278 BRANCH=none TEST=Kinox can get the 90w barrel adapter. Signed-off-by: Matt Wang <matt_wang@compal.corp-partner.google.com> Change-Id: I84455d1028b2cfc4297e10410092454f3dd61bc2 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3521743 Reviewed-by: Elmo Lan <elmo_lan@compal.corp-partner.google.com> Reviewed-by: Zhuohao Lee <zhuohao@chromium.org>
-rw-r--r--board/kinox/board.h18
-rw-r--r--board/kinox/build.mk1
-rw-r--r--board/kinox/power_detection.c327
-rw-r--r--board/kinox/sensors.c12
4 files changed, 358 insertions, 0 deletions
diff --git a/board/kinox/board.h b/board/kinox/board.h
index b2ede09c16..ba67aa07c5 100644
--- a/board/kinox/board.h
+++ b/board/kinox/board.h
@@ -124,6 +124,22 @@
#include "registers.h"
#include "usbc_config.h"
+enum adp_id {
+ TINY = 1,
+ TIO1,
+ TIO2
+};
+
+struct adpater_id_params {
+ int min_voltage;
+ int max_voltage;
+ int charge_voltage;
+ int charge_current;
+ int watt;
+ int obp95;
+ int obp85;
+};
+
enum charge_port {
CHARGE_PORT_TYPEC0,
CHARGE_PORT_BARRELJACK,
@@ -135,7 +151,9 @@ enum adc_channel {
ADC_TEMP_SENSOR_2_CPU_VR,
ADC_TEMP_SENSOR_3_WIFI,
ADC_TEMP_SENSOR_4_DIMM,
+ ADC_PWR_IN_IMON,
ADC_VBUS,
+ ADC_ADP_ID,
ADC_CH_COUNT
};
diff --git a/board/kinox/build.mk b/board/kinox/build.mk
index 9c668e0e2a..440d137968 100644
--- a/board/kinox/build.mk
+++ b/board/kinox/build.mk
@@ -13,6 +13,7 @@ BASEBOARD:=brask
board-y=
board-y+=board.o
+board-y+=power_detection.o
board-y+=fans.o
board-y+=fw_config.o
board-y+=i2c.o
diff --git a/board/kinox/power_detection.c b/board/kinox/power_detection.c
new file mode 100644
index 0000000000..575ec0e8aa
--- /dev/null
+++ b/board/kinox/power_detection.c
@@ -0,0 +1,327 @@
+/* Copyright 2022 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 "charge_manager.h"
+#include "chipset.h"
+#include "common.h"
+#include "compile_time_macros.h"
+#include "console.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "power.h"
+#include "registers.h"
+#include "task.h"
+#include "timer.h"
+#include "util.h"
+
+/* Console output macros */
+#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args)
+
+/******************************************************************************/
+
+static const char * const adp_id_names[] = {
+ "unknown",
+ "tiny",
+ "tio1",
+ "tio2",
+};
+
+/* ADP_ID control */
+struct adpater_id_params tio1_power[] = {
+ {
+ .min_voltage = 3300,
+ .max_voltage = 3300,
+ .charge_voltage = 20000,
+ .charge_current = 6000,
+ .watt = 120,
+ .obp95 = 1990,
+ .obp85 = 1780,
+ },
+};
+
+struct adpater_id_params tio2_power[] = {
+ {
+ .min_voltage = 0,
+ .max_voltage = 68,
+ .charge_voltage = 20000,
+ .charge_current = 8500,
+ .watt = 170,
+ .obp95 = 2820,
+ .obp85 = 916,
+ },
+ {
+ .min_voltage = 68,
+ .max_voltage = 142,
+ .charge_voltage = 20000,
+ .charge_current = 2250,
+ .watt = 45,
+ .obp95 = 750,
+ .obp85 = 670,
+ },
+ {
+ .min_voltage = 200,
+ .max_voltage = 288,
+ .charge_voltage = 20000,
+ .charge_current = 3250,
+ .watt = 65,
+ .obp95 = 1080,
+ .obp85 = 960,
+ },
+ {
+ .min_voltage = 531,
+ .max_voltage = 607,
+ .charge_voltage = 20000,
+ .charge_current = 6000,
+ .watt = 120,
+ .obp95 = 1990,
+ .obp85 = 1780,
+ },
+ {
+ .min_voltage = 384,
+ .max_voltage = 480,
+ .charge_voltage = 20000,
+ .charge_current = 7500,
+ .watt = 150,
+ .obp95 = 2490,
+ .obp85 = 2220,
+ },
+ {
+ .min_voltage = 1062,
+ .max_voltage = 1126,
+ .charge_voltage = 20000,
+ .charge_current = 8500,
+ .watt = 170,
+ .obp95 = 2820,
+ .obp85 = 916,
+ },
+ {
+ .min_voltage = 2816,
+ .max_voltage = 3300,
+ .charge_voltage = 20000,
+ .charge_current = 6000,
+ .watt = 120,
+ .obp95 = 1990,
+ .obp85 = 1780,
+ },
+};
+
+struct adpater_id_params tiny_power[] = {
+ {
+ .min_voltage = 68,
+ .max_voltage = 142,
+ .charge_voltage = 20000,
+ .charge_current = 2250,
+ .watt = 45,
+ .obp95 = 750,
+ .obp85 = 670,
+ },
+ {
+ .min_voltage = 200,
+ .max_voltage = 288,
+ .charge_voltage = 20000,
+ .charge_current = 3250,
+ .watt = 65,
+ .obp95 = 1080,
+ .obp85 = 960,
+ },
+ {
+ .min_voltage = 384,
+ .max_voltage = 480,
+ .charge_voltage = 20000,
+ .charge_current = 4500,
+ .watt = 90,
+ .obp95 = 1490,
+ .obp85 = 1330,
+ },
+ {
+ .min_voltage = 531,
+ .max_voltage = 607,
+ .charge_voltage = 20000,
+ .charge_current = 6000,
+ .watt = 120,
+ .obp95 = 0x2D3,
+ .obp85 = 0x286,
+ },
+ {
+ .min_voltage = 653,
+ .max_voltage = 783,
+ .charge_voltage = 20000,
+ .charge_current = 6750,
+ .watt = 135,
+ .obp95 = 2240,
+ .obp85 = 2000,
+ },
+ {
+ .min_voltage = 851,
+ .max_voltage = 997,
+ .charge_voltage = 20000,
+ .charge_current = 7500,
+ .watt = 150,
+ .obp95 = 2490,
+ .obp85 = 2220,
+ },
+ {
+ .min_voltage = 1063,
+ .max_voltage = 1226,
+ .charge_voltage = 20000,
+ .charge_current = 8500,
+ .watt = 170,
+ .obp95 = 2820,
+ .obp85 = 916,
+ },
+ {
+ .min_voltage = 1749,
+ .max_voltage = 1968,
+ .charge_voltage = 20000,
+ .charge_current = 11500,
+ .watt = 230,
+ .obp95 = 3810,
+ .obp85 = 3410,
+ },
+};
+
+struct adpater_id_params power_type[8];
+static int adp_id_value_debounce;
+
+void obp_point_95(void)
+{
+ /* Disable this interrupt while it's asserted. */
+ npcx_adc_thresh_int_enable(NPCX_ADC_THRESH1, 0);
+ /* Enable the voltage low interrupt. */
+ npcx_adc_thresh_int_enable(NPCX_ADC_THRESH2, 1);
+
+ /* Trigger the PROCHOT */
+ gpio_set_level(GPIO_EC_PROCHOT_ODL, 0);
+ CPRINTF("Adapter voltage over then 95%% trigger prochot.");
+}
+
+void obp_point_85(void)
+{
+ /* Disable this interrupt while it's asserted. */
+ npcx_adc_thresh_int_enable(NPCX_ADC_THRESH2, 0);
+ /* Enable the voltage high interrupt. */
+ npcx_adc_thresh_int_enable(NPCX_ADC_THRESH1, 1);
+
+ /* Release the PROCHOT */
+ gpio_set_level(GPIO_EC_PROCHOT_ODL, 1);
+ CPRINTF("Adapter voltage less then 85%% release prochot.");
+}
+
+struct npcx_adc_thresh_t adc_obp_point_95 = {
+ .adc_ch = ADC_PWR_IN_IMON,
+ .adc_thresh_cb = obp_point_95,
+ .thresh_assert = 3300, /* Default */
+};
+
+struct npcx_adc_thresh_t adc_obp_point_85 = {
+ .adc_ch = ADC_PWR_IN_IMON,
+ .adc_thresh_cb = obp_point_85,
+ .lower_or_higher = 1,
+ .thresh_assert = 0, /* Default */
+};
+
+static void set_up_adc_irqs(void)
+{
+ /* Set interrupt thresholds for the ADC. */
+ CPRINTS("%s", __func__);
+ npcx_adc_register_thresh_irq(NPCX_ADC_THRESH1, &adc_obp_point_95);
+ npcx_adc_register_thresh_irq(NPCX_ADC_THRESH2, &adc_obp_point_85);
+ npcx_set_adc_repetitive(adc_channels[ADC_PWR_IN_IMON].input_ch, 1);
+ npcx_adc_thresh_int_enable(NPCX_ADC_THRESH1, 1);
+ npcx_adc_thresh_int_enable(NPCX_ADC_THRESH2, 1);
+}
+
+/*
+ * Scalar change to Scalar change to
+ * downgrade voltage 3.3V voltage
+ * | |
+ * | SIO collect | SIO collect
+ * | 1st adapter | 2nd adapter
+ * | information | information
+ * | | | | | | | | | |
+ * -------------------------------------------------------
+ * | | |
+ * |---220 ms---|-----400 ms-----|
+ *
+ * Tiny: Twice adapter ADC values are less than 0x3FF.
+ * TIO1: Twice adapter ADC values are 0x3FF.
+ * TIO2: First adapter ADC value less than 0x3FF.
+ * Second adpater ADC value is 0x3FF.
+ */
+static void adp_id_deferred(void);
+DECLARE_DEFERRED(adp_id_deferred);
+void adp_id_deferred(void)
+{
+ struct charge_port_info pi = { 0 };
+ int i = 0;
+ int adp_type = 0;
+ int adp_id_value;
+ int adp_finial_adc_value;
+ int power_type_len = 0;
+
+ adp_id_value = adc_read_channel(ADC_ADP_ID);
+
+ if (!adp_id_value_debounce) {
+ adp_id_value_debounce = adp_id_value;
+ /* for delay the 400ms to get the next APD_ID value */
+ hook_call_deferred(&adp_id_deferred_data, 400 * MSEC);
+ } else if (adp_id_value_debounce == 0x3FF && adp_id_value == 0x3FF) {
+ adp_finial_adc_value = adp_id_value;
+ adp_type = TIO1;
+ } else if (adp_id_value_debounce < 0x3FF && adp_id_value == 0x3FF) {
+ adp_finial_adc_value = adp_id_value_debounce;
+ adp_type = TIO2;
+ } else if (adp_id_value_debounce < 0x3FF && adp_id_value < 0x3FF) {
+ adp_finial_adc_value = adp_id_value;
+ adp_type = TINY;
+ } else {
+ CPRINTS("ADP_ID mismatch anything!");
+ /* Set the default shipping adaptor max ADC value */
+ adp_finial_adc_value = 0x69;
+ adp_type = TINY;
+ }
+
+
+ switch (adp_type) {
+ case TIO1:
+ power_type_len = sizeof(tio1_power) /
+ sizeof(struct adpater_id_params);
+ memcpy(&power_type, &tio1_power, sizeof(tio1_power));
+ break;
+ case TIO2:
+ power_type_len = sizeof(tio2_power) /
+ sizeof(struct adpater_id_params);
+ memcpy(&power_type, &tio2_power, sizeof(tio2_power));
+ break;
+ case TINY:
+ power_type_len = sizeof(tiny_power) /
+ sizeof(struct adpater_id_params);
+ memcpy(&power_type, &tiny_power, sizeof(tiny_power));
+ break;
+ }
+
+ for (i = 0; (i < power_type_len) && adp_type; i++) {
+ if (adp_finial_adc_value <= power_type[i].max_voltage) {
+ adc_obp_point_95.thresh_assert = power_type[i].obp95;
+ adc_obp_point_85.thresh_assert = power_type[i].obp85;
+ pi.voltage = power_type[i].charge_voltage;
+ pi.current = power_type[i].charge_current;
+ set_up_adc_irqs();
+ charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED,
+ DEDICATED_CHARGE_PORT, &pi);
+ CPRINTS("Power type %s, %dW", adp_id_names[adp_type],
+ power_type[i].watt);
+ break;
+ }
+ }
+}
+
+static void adp_id_init(void)
+{
+ /* Delay 220ms to get the first ADP_ID value */
+ hook_call_deferred(&adp_id_deferred_data, 220 * MSEC);
+}
+DECLARE_HOOK(HOOK_INIT, adp_id_init, HOOK_PRIO_DEFAULT);
diff --git a/board/kinox/sensors.c b/board/kinox/sensors.c
index a828904593..e444664e8f 100644
--- a/board/kinox/sensors.c
+++ b/board/kinox/sensors.c
@@ -46,6 +46,18 @@ const struct adc_t adc_channels[] = {
.factor_mul = ADC_MAX_VOLT * 39,
.factor_div = (ADC_READ_MAX + 1) * 5,
},
+ [ADC_PWR_IN_IMON] = {
+ .name = "PWR_IN_IMON",
+ .input_ch = NPCX_ADC_CH3,
+ .factor_mul = ADC_MAX_VOLT,
+ .factor_div = ADC_READ_MAX + 1,
+ },
+ [ADC_ADP_ID] = {
+ .name = "ADP_ID",
+ .input_ch = NPCX_ADC_CH4,
+ .factor_mul = ADC_MAX_VOLT,
+ .factor_div = ADC_READ_MAX + 1,
+ },
};
BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT);