blob: 39f41ddddb1ee4b3961e167773cc6c7433d8916f (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
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;
}
|