summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic (Chun-Ju) Yang <victoryang@chromium.org>2014-04-17 18:04:38 +0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-04-24 11:36:43 +0000
commitd02e8c2090f7cd57098016d520b538e61870beb5 (patch)
treef58b4b9aa20f5bcf82e08efed43b0f697360d875
parent295e409ea9ab10adb34b13330a2b9948e43da58c (diff)
downloadchrome-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.c3
-rw-r--r--board/keyborg/build.mk2
-rw-r--r--board/keyborg/hardware.c15
-rw-r--r--board/keyborg/master_slave.c117
-rw-r--r--board/keyborg/master_slave.h36
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 */