summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2012-11-29 10:51:08 -0800
committerRandall Spangler <rspangler@chromium.org>2012-11-29 12:07:13 -0800
commit0549d1adf35fd53282455bbec686a3437217938b (patch)
tree25ed1a6b83b33080b6d020acc953b6bf68699c38
parentad2d36dbd4bfa4043931108b287d9a49df1965ca (diff)
downloadchrome-ec-0549d1adf35fd53282455bbec686a3437217938b.tar.gz
link: Disable interrupts while reading/writing bits via onewire
When reading, the line must be sampled in a narrow timing window after the output pulse. Interrupts or context switches during this time corrupt the data. Similarly, when writing, the difference between a 0-bit and a 1-bit is the length of the output pulse. So a context switch or interrupt there can turn a 1-bit into a 0-bit. BUG=chrome-os-partner:15507 BRANCH=link TEST=manual 0. plug in AC power 1. hold down shift key for the duration of this test 2. powerled yellow 3. powerled red 4. repeat steps 2-3 several times 5. release shift key Power adapter LED should toggle color each time. (It may also toggle to the normally expected color during this experiment, if the charging task updates it.) Power adapter LED should NOT turn off during this test. Original-Change-Id: Ief11e6e9a5b07aa3a25c60c50e4e7744a4705713 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/38925 Reviewed-by: Yung-Chieh Lo <yjlou@chromium.org> Reviewed-by: Vincent Palatin <vpalatin@chromium.org> (cherry picked from commit 52440ef89387809af91051671a98ea9c36ce27ca) Change-Id: I19e72b0d2fc02c6d2a13b0c7f6efc464c1e54c15 Reviewed-on: https://gerrit.chromium.org/gerrit/38934 Reviewed-by: Randall Spangler <rspangler@chromium.org> Tested-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--chip/lm4/onewire.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/chip/lm4/onewire.c b/chip/lm4/onewire.c
index d505ff5c08..458b70c269 100644
--- a/chip/lm4/onewire.c
+++ b/chip/lm4/onewire.c
@@ -9,6 +9,7 @@
#include "gpio.h"
#include "hooks.h"
#include "registers.h"
+#include "task.h"
#include "timer.h"
#define ONEWIRE_PIN (1<<2) /* One-wire pin mask (on GPIO H) */
@@ -51,6 +52,12 @@ static int readbit(void)
{
int bit;
+ /*
+ * The delay between sending the output pulse and reading the bit is
+ * extremely timing sensitive, so disable interrupts.
+ */
+ interrupt_disable();
+
/* Output low */
output0(T_RL);
@@ -60,6 +67,13 @@ static int readbit(void)
/* Read bit */
bit = readline();
+ /*
+ * Enable interrupt as soon as we've read the bit. The delay to the
+ * end of the timeslot is a lower bound, so additional latency here is
+ * harmless.
+ */
+ interrupt_enable();
+
/* Delay to end of timeslot */
udelay(T_SLOT - T_MSR);
return bit;
@@ -69,13 +83,25 @@ static int readbit(void)
/* Write a bit */
static void writebit(int bit)
{
+ /*
+ * The delays in the output-low signal for sending 0 and 1 bits are
+ * extremely timing sensitive, so disable interrupts during that time.
+ * Interrupts can be enabled again as soon as the output is switched
+ * back to open-drain, since the delay for the rest of the timeslot is
+ * a lower bound.
+ */
if (bit) {
+ interrupt_disable();
output0(T_W1L);
+ interrupt_enable();
udelay(T_SLOT - T_W1L);
} else {
+ interrupt_disable();
output0(T_W0L);
+ interrupt_enable();
udelay(T_SLOT - T_W0L);
}
+
}