diff options
author | Randall Spangler <rspangler@chromium.org> | 2013-08-02 13:53:20 -0700 |
---|---|---|
committer | ChromeBot <chrome-bot@google.com> | 2013-08-02 18:22:57 -0700 |
commit | 219b02604cea6f5b9d245f49913544eae82b3694 (patch) | |
tree | f44851d34cde108e109f77b9a182cc03c1dfcbd2 /common/onewire.c | |
parent | a566d8d9e42d6f25503e8c897a995fef0b6ae42b (diff) | |
download | chrome-ec-219b02604cea6f5b9d245f49913544eae82b3694.tar.gz |
Move onewire bus support from chip/lm4 to common
No functional changes; just moving file
BUG=chrome-os-partner:21612
BRANCH=none
TEST=onewire red / onewire green / onewire yellow all set the adapter LED
(tested on link, since I don't have a bolt, but the EC chip and adapter
are identical)
Change-Id: I005abf871caafa39e82e88875b515c842a12d591
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/64376
Reviewed-by: Vic Yang <victoryang@chromium.org>
Diffstat (limited to 'common/onewire.c')
-rw-r--r-- | common/onewire.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/common/onewire.c b/common/onewire.c new file mode 100644 index 0000000000..e57d6db5a1 --- /dev/null +++ b/common/onewire.c @@ -0,0 +1,144 @@ +/* Copyright (c) 2012 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. + */ + +/* 1-wire interface module for Chrome EC */ + +#include "common.h" +#include "gpio.h" +#include "task.h" +#include "timer.h" + +/* + * Standard speed; all timings padded by 2 usec for safety. + * + * Note that these timing are actually _longer_ than legacy 1-wire standard + * speed because we're running the 1-wire bus at 3.3V instead of 5V. + */ +#define T_RSTL 602 /* Reset low pulse; 600-960 us */ +#define T_MSP 72 /* Presence detect sample time; 70-75 us */ +#define T_RSTH (68 + 260 + 5 + 2) /* Reset high; tPDHmax + tPDLmax + tRECmin */ +#define T_SLOT 70 /* Timeslot; >67 us */ +#define T_W0L 63 /* Write 0 low; 62-120 us */ +#define T_W1L 7 /* Write 1 low; 5-15 us */ +#define T_RL 7 /* Read low; 5-15 us */ +#define T_MSR 9 /* Read sample time; <15 us. Must be at least 200 ns after + * T_RL since that's how long the signal takes to be pulled + * up on our board. */ + +/** + * Output low on the bus for <usec> us, then switch back to open-drain input. + */ +static void output0(int usec) +{ + gpio_set_flags(GPIO_ONEWIRE, + GPIO_OPEN_DRAIN | GPIO_OUTPUT | GPIO_OUT_LOW); + udelay(usec); + gpio_set_flags(GPIO_ONEWIRE, GPIO_INPUT); +} + +/** + * Read a bit. + */ +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); + + /* Delay to let slave release the line if it wants to send a 1-bit */ + udelay(T_MSR - T_RL); + + /* Read bit */ + bit = gpio_get_level(GPIO_ONEWIRE); + + /* + * 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; +} + +/** + * 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); + } + +} + +int onewire_reset(void) +{ + /* Start transaction with master reset pulse */ + output0(T_RSTL); + + /* Wait for presence detect sample time. + * + * (Alternately, we could poll waiting for a 1-bit indicating our pulse + * has let go, then poll up to max time waiting for a 0-bit indicating + * the slave has responded.) + */ + udelay(T_MSP); + + if (gpio_get_level(GPIO_ONEWIRE)) + return EC_ERROR_UNKNOWN; + + /* + * Wait for end of presence pulse. + * + * (Alternately, we could poll waiting for a 1-bit.) + */ + udelay(T_RSTH - T_MSP); + + return EC_SUCCESS; +} + +int onewire_read(void) +{ + int data = 0; + int i; + + for (i = 0; i < 8; i++) + data |= readbit() << i; /* LSB first */ + + return data; +} + +void onewire_write(int data) +{ + int i; + + for (i = 0; i < 8; i++) + writebit((data >> i) & 0x01); /* LSB first */ +} |