diff options
author | Randall Spangler <rspangler@chromium.org> | 2012-11-29 10:51:08 -0800 |
---|---|---|
committer | Randall Spangler <rspangler@chromium.org> | 2012-11-29 12:07:13 -0800 |
commit | 0549d1adf35fd53282455bbec686a3437217938b (patch) | |
tree | 25ed1a6b83b33080b6d020acc953b6bf68699c38 | |
parent | ad2d36dbd4bfa4043931108b287d9a49df1965ca (diff) | |
download | chrome-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.c | 26 |
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); } + } |