summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorVic Yang <victoryang@google.com>2015-01-26 15:40:50 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-01-30 05:11:06 +0000
commitb7f7cdaa72dbb82a00d3e2eae8c82268b838e988 (patch)
treef3b97c53cc19864f529dc1d63b5c78d306391ca9 /common
parent920d701647c4c7d0d75aa793a9ea0a8e035f2206 (diff)
downloadchrome-ec-b7f7cdaa72dbb82a00d3e2eae8c82268b838e988.tar.gz
ryu: improve inductive charging control
When inductive charging just starts, there might be a blip on CHARGE_DONE signal and it'd cause our charging control logic to shut down charging. Fix this by waiting for a second before we start monitoring CHARGE_DONE. Also, once we see CHARGE_DONE=1 and disable charging, CHARGE_DONE will go low. Handle this by ignoring all subsequent CHARGE_DONE change until the next time the lid is opened. BRANCH=Ryu BUG=None TEST=Pass the updated unit test. TEST=Charge a base on Ryu P3. Change-Id: I9d911cd689d8e88ebcd66e6eca7c86dd70704880 Signed-off-by: Vic Yang <victoryang@google.com> Reviewed-on: https://chromium-review.googlesource.com/243365 Tested-by: Vic Yang <victoryang@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org> Reviewed-by: Vincent Palatin <vpalatin@chromium.org> Commit-Queue: Vic Yang <victoryang@chromium.org>
Diffstat (limited to 'common')
-rw-r--r--common/inductive_charging.c60
1 files changed, 56 insertions, 4 deletions
diff --git a/common/inductive_charging.c b/common/inductive_charging.c
index 0021cc3ac6..8b92394c8c 100644
--- a/common/inductive_charging.c
+++ b/common/inductive_charging.c
@@ -8,22 +8,74 @@
#include "common.h"
#include "gpio.h"
#include "hooks.h"
+#include "inductive_charging.h"
#include "lid_switch.h"
#include "timer.h"
+/*
+ * The inductive charger is controlled with two signals:
+ * - BASE_CHG_VDD_EN controls whether the charger is powered.
+ * - CHARGE_EN controls whether to enable charging.
+ * Charging status is reported via CHARGE_DONE, but in a tricky way:
+ * - It's 0 if:
+ * + The charger is unpowered. (i.e. BASE_CHG_VDD_EN = 0)
+ * + Or charging is disabled. (i.e. CHARGE_EN = 0)
+ * + Or the charging current is small enough.
+ * - Otherwise, it's 1.
+ */
+
+/* Whether we want to process interrupts on CHARGE_DONE or not. */
+static int monitor_charge_done;
+
+/*
+ * Start monitoring CHARGE_DONE and fires the interrupt once so that
+ * we react to the current value.
+ */
+static void inductive_charging_monitor_charge(void)
+{
+ monitor_charge_done = 1;
+ inductive_charging_interrupt(GPIO_CHARGE_DONE);
+}
+DECLARE_DEFERRED(inductive_charging_monitor_charge);
+
void inductive_charging_interrupt(enum gpio_signal signal)
{
int charger_enabled = gpio_get_level(GPIO_BASE_CHG_VDD_EN);
int charge_done = gpio_get_level(GPIO_CHARGE_DONE);
+ static int charge_already_done;
+
+ if (!monitor_charge_done && signal == GPIO_CHARGE_DONE)
+ return;
- /* Always try to charge if the lid is just closed */
- if (signal == GPIO_LID_OPEN)
+ if (signal == GPIO_LID_OPEN) {
+ /* The lid has been opened. Clear all states. */
charge_done = 0;
+ charge_already_done = 0;
+ monitor_charge_done = 0;
+ } else if (signal == GPIO_CHARGE_DONE) {
+ /*
+ * Once we see CHARGE_DONE=1, we ignore any change on
+ * CHARGE_DONE until the next time the lid is opened.
+ */
+ if (charge_done == 1)
+ charge_already_done = 1;
+ else if (charge_already_done)
+ return;
+ }
- if (!charger_enabled || charge_done)
+ if (!charger_enabled || charge_done) {
gpio_set_level(GPIO_CHARGE_EN, 0);
- else
+ } else {
gpio_set_level(GPIO_CHARGE_EN, 1);
+ /*
+ * When the charging is just enabled, there might be a
+ * blip on CHARGE_DONE. Wait for a second before we start
+ * looking at CHARGE_DONE.
+ */
+ if (!monitor_charge_done)
+ hook_call_deferred(inductive_charging_monitor_charge,
+ SECOND);
+ }
}
static void inductive_charging_deferred_update(void)