summaryrefslogtreecommitdiff
path: root/chip
diff options
context:
space:
mode:
Diffstat (limited to 'chip')
-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 082ce1238a..0c795eeedc 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) */
@@ -56,6 +57,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);
@@ -65,6 +72,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;
@@ -75,13 +89,25 @@ static int readbit(void)
*/
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);
}
+
}
int onewire_reset(void)