-
Notifications
You must be signed in to change notification settings - Fork 15
/
A1-desk-board-selector.c
158 lines (137 loc) · 3.18 KB
/
A1-desk-board-selector.c
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include <sys/ioctl.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <stdint.h>
#include <stdbool.h>
#include <fcntl.h>
#include "miner.h"
struct pcf8575_ctx {
uint8_t addr;
uint8_t p0;
uint8_t p1;
int file;
uint8_t active_board;
pthread_mutex_t lock;
};
static struct pcf8575_ctx board_ctx = { 0x27, 0xff, 0xff, -1, .active_board = 255,};
#define UNUSED_BITS 0xe0
#define SLEEP_MS_AFTER_CS 0
static bool pcf8575_write(void)
{
union i2c_smbus_data data;
data.byte = board_ctx.p1 | UNUSED_BITS;
struct i2c_smbus_ioctl_data args;
__s32 err;
args.read_write = I2C_SMBUS_WRITE;
args.command = board_ctx.p0 | UNUSED_BITS;
args.size = I2C_SMBUS_BYTE_DATA;
args.data = &data;
err = ioctl(board_ctx.file, I2C_SMBUS, &args);
if (err == -1) {
fprintf(stderr,
"Error: Failed to write: %s\n",
strerror(errno));
err = -errno;
} else {
applog(LOG_DEBUG, "written: 0x%02x, 0x%02x", board_ctx.p0, board_ctx.p1);
// usleep(25000);
cgsleep_ms(SLEEP_MS_AFTER_CS);
}
return err == 0;
}
void lock_board_selector(void)
{
// applog(LOG_WARNING, "lock_board_selector()");
mutex_lock(&board_ctx.lock);
}
void unlock_board_selector(void)
{
// applog(LOG_WARNING, "unlock_board_selector()");
mutex_unlock(&board_ctx.lock);
}
bool a1_board_selector_init(void)
{
mutex_init(&board_ctx.lock);
applog(LOG_WARNING, "a1_board_selector_init()");
board_ctx.file = open("/dev/i2c-1", O_RDWR);
if (board_ctx.file < 0) {
fprintf(stderr,
"Error: Could not open i2c-1: %s\n",
board_ctx.addr, strerror(errno));
return false;
}
if (ioctl(board_ctx.file, I2C_SLAVE, board_ctx.addr) < 0) {
fprintf(stderr,
"Error: Could not set address to 0x%02x: %s\n",
board_ctx.addr, strerror(errno));
return false;
}
return pcf8575_write();
}
void a1_board_selector_exit(void)
{
close(board_ctx.file);
board_ctx.file = -1;
}
bool a1_board_selector_select_board(uint8_t board)
{
if (board > 7)
return false;
// applog(LOG_WARNING, "board_selector_select_board(%d)", board);
lock_board_selector();
if (board_ctx.active_board == board)
return true;
board_ctx.active_board = board;
board_ctx.p0 = 1 << board_ctx.active_board;
board_ctx.p1 = 0xff;
bool retval = pcf8575_write();
return retval;
}
static bool __board_selector_reset(void)
{
board_ctx.p1 = ~board_ctx.p0;
if (!pcf8575_write())
return false;
usleep(1000000);
board_ctx.p1 = 0xff;
if (!pcf8575_write())
return false;
usleep(1000000);
return true;
}
// we assume we are already holding the mutex
bool a1_board_selector_reset_board(void)
{
// lock_board_selector();
bool retval = __board_selector_reset();
// unlock_board_selector();
return retval;
}
bool a1_board_selector_reset_all_boards(void)
{
lock_board_selector();
board_ctx.p1 = 0;
bool retval = __board_selector_reset();
unlock_board_selector();
return retval;
}
#if 0
int main(void)
{
if (init_pcf8575(&board_ctx)) {
if (!pcf8575_write(&g_ctx)) {
fprintf(stderr,
"Error: Failed to write: %s\n",
strerror(errno));
}
a1_board_selector_exit(&g_ctx);
}
return 0;
}
#endif
/////////////////////////////////////////////////////////////////////////////