diff options
author | Vic (Chun-Ju) Yang <victoryang@chromium.org> | 2014-04-17 18:04:38 +0800 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-04-24 11:36:43 +0000 |
commit | d02e8c2090f7cd57098016d520b538e61870beb5 (patch) | |
tree | f58b4b9aa20f5bcf82e08efed43b0f697360d875 | |
parent | 295e409ea9ab10adb34b13330a2b9948e43da58c (diff) | |
download | chrome-ec-d02e8c2090f7cd57098016d520b538e61870beb5.tar.gz |
Keyborg: Implement master/slave identification
The two chips work together, so let's teach them how to tell master from
slave. After identification, the two chips shake hands through the two
sync signals.
BUG=None
TEST=Disable handshake on master. See slave fail. Vice versa.
BRANCH=None
Change-Id: Idb6a56128f608dd2ee5c453f75abea475fe1779f
Signed-off-by: Vic (Chun-Ju) Yang <victoryang@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/195395
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r-- | board/keyborg/board.c | 3 | ||||
-rw-r--r-- | board/keyborg/build.mk | 2 | ||||
-rw-r--r-- | board/keyborg/hardware.c | 15 | ||||
-rw-r--r-- | board/keyborg/master_slave.c | 117 | ||||
-rw-r--r-- | board/keyborg/master_slave.h | 36 |
5 files changed, 170 insertions, 3 deletions
diff --git a/board/keyborg/board.c b/board/keyborg/board.c index c21510530f..1e4096f90c 100644 --- a/board/keyborg/board.c +++ b/board/keyborg/board.c @@ -7,6 +7,7 @@ #include "board.h" #include "common.h" #include "debug.h" +#include "master_slave.h" #include "registers.h" #include "system.h" #include "task.h" @@ -18,6 +19,8 @@ int main(void) hardware_init(); debug_printf("Keyborg starting...\n"); + master_slave_init(); + while (1) { i++; task_wait_event(SECOND); diff --git a/board/keyborg/build.mk b/board/keyborg/build.mk index d9f17bb5c3..39eb64c284 100644 --- a/board/keyborg/build.mk +++ b/board/keyborg/build.mk @@ -9,5 +9,5 @@ CHIP:=stm32 CHIP_FAMILY:=stm32f CHIP_VARIANT:=stm32ts60 -board-y=board.o hardware.o runtime.o +board-y=board.o hardware.o runtime.o master_slave.o board-$(CONFIG_DEBUG_PRINTF)+=debug.o diff --git a/board/keyborg/hardware.c b/board/keyborg/hardware.c index d6fa3755d0..76c3c5f1f9 100644 --- a/board/keyborg/hardware.c +++ b/board/keyborg/hardware.c @@ -52,10 +52,11 @@ static void power_init(void) #define OUT50(n) (0x3 << ((n & 0x7) * 4)) #define ANALOG(n) (0x0) #define FLOAT(n) (0x4 << ((n & 0x7) * 4)) -#define GP_PP(n) (0x0) #define GP_OD(n) (0x4 << ((n & 0x7) * 4)) #define AF_PP(n) (0x8 << ((n & 0x7) * 4)) #define AF_OD(n) (0xc << ((n & 0x7) * 4)) +#define LOW(n) (1 << (n + 16)) +#define HIGH(n) (1 << n) static void pins_init(void) { @@ -64,9 +65,19 @@ static void pins_init(void) | (2 << 24); /* Pin usage: + * PA0: SPI_NSS - INPUT/INT_FALLING + * PA1: N_CHG - OUTPUT/LOW + * PA6: CS1 - OUTPUT/HIGH * PA15: UART TX - OUTPUT/HIGH + * PI1: SYNC1 - OUTPUT/LOW + * PI2: SYNC2 - OUTPUT/LOW */ - STM32_GPIO_CRH(GPIO_A) = OUT(15) | GP_PP(15); + STM32_GPIO_CRL(GPIO_A) = OUT(1) | OUT(6) | FLOAT(0); + STM32_GPIO_CRH(GPIO_A) = OUT(15); + STM32_GPIO_BSRR(GPIO_A) = LOW(1) | HIGH(6) | HIGH(15); + + STM32_GPIO_CRL(GPIO_I) = OUT(1) | OUT(2); + STM32_GPIO_BSRR(GPIO_I) = LOW(1) | LOW(2); } static void adc_init(void) diff --git a/board/keyborg/master_slave.c b/board/keyborg/master_slave.c new file mode 100644 index 0000000000..39f41ddddb --- /dev/null +++ b/board/keyborg/master_slave.c @@ -0,0 +1,117 @@ +/* Copyright (c) 2014 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. + */ +/* Master/slave identification */ + +#include "board.h" +#include "debug.h" +#include "master_slave.h" +#include "registers.h" +#include "timer.h" +#include "util.h" + +#define SYNC1 (1 << 1) /* PI1 */ +#define SYNC2 (1 << 2) /* PI2 */ + +static int is_master = -1; +static int last_sync; /* = 0 -> Low */ + +int master_slave_is_master(void) +{ + return is_master; +} + +static int wait_sync_signal(int mask, int v, int timeout_ms) +{ + uint32_t start = get_time().val; + + while ((!!(STM32_GPIO_IDR(GPIO_I) & mask)) != v) { + if ((get_time().val - start) >= timeout_ms * MSEC) + return EC_ERROR_TIMEOUT; + } + return EC_SUCCESS; +} + +int master_slave_sync(int timeout_ms) +{ + int err = EC_SUCCESS; + last_sync ^= 1; + if (is_master) { + STM32_GPIO_BSRR(GPIO_I) = SYNC1 << (last_sync ? 0 : 16); + if (wait_sync_signal(SYNC2, last_sync, timeout_ms)) + err = EC_ERROR_TIMEOUT; + } else { + if (wait_sync_signal(SYNC1, last_sync, timeout_ms)) + err = EC_ERROR_TIMEOUT; + STM32_GPIO_BSRR(GPIO_I) = SYNC2 << (last_sync ? 0 : 16); + } + return err; +} + +static int master_handshake(void) +{ + uint32_t val; + int err; + + /* SYNC2 -> GPIO_INPUT */ + val = STM32_GPIO_CRL(GPIO_I); + val &= ~0x00000f00; + val |= 0x00000400; + STM32_GPIO_CRL(GPIO_I) = val; + + err = master_slave_sync(1000); + err |= master_slave_sync(20); + err |= master_slave_sync(20); + + return err; +} + +static int slave_handshake(void) +{ + uint32_t val; + int err; + + /* SYNC1 -> GPIO_INPUT */ + val = STM32_GPIO_CRL(GPIO_I); + val &= ~0x000000f0; + val |= 0x00000040; + STM32_GPIO_CRL(GPIO_I) = val; + + err = master_slave_sync(1000); + err |= master_slave_sync(20); + err |= master_slave_sync(20); + + return err; +} + +static void master_slave_check(void) +{ + if (STM32_GPIO_IDR(GPIO_A) & (1 << 0) /* NSS */) { + debug_printf("I'm slave\n"); + is_master = 0; + } else { + debug_printf("I'm master\n"); + is_master = 1; + } +} + +int master_slave_init(void) +{ + int handshake_err; + + master_slave_check(); + + if (is_master) + handshake_err = master_handshake(); + else + handshake_err = slave_handshake(); + + if (handshake_err != EC_SUCCESS) + debug_printf("handshake error\n"); + else + debug_printf("handshake done\n"); + + return handshake_err; +} + diff --git a/board/keyborg/master_slave.h b/board/keyborg/master_slave.h new file mode 100644 index 0000000000..b64b88819e --- /dev/null +++ b/board/keyborg/master_slave.h @@ -0,0 +1,36 @@ +/* Copyright (c) 2014 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. + */ +/* Master/slave identification */ + +#ifndef __BOARD_KEYBORG_MASTER_SLAVE_H +#define __BOARD_KEYBORG_MASTER_SLAVE_H + +/** + * Get the identity of this chip. + * + * @return 1 if master; otherwise, 0. + */ +int master_slave_is_master(void); + +/** + * Synchronize with the other chip. The other chip must also call this + * function to synchronize. + * + * @param timeout_ms Timeout value in millisecond. If the other chip + * doesn't synchronize within this time, the sync + * call fails. + * + * @return EC_SUCCESS, or non-zero if any error. + */ +int master_slave_sync(int timeout_ms); + +/** + * Identify this chip and shake hands with the other chip. + * + * @return EC_SUCCESS, or non-zero if any error. + */ +int master_slave_init(void); + +#endif /* __BOARD_KEYBORG_MASTER_SLAVE_H */ |