blob: 7357c14e10599caf288503e2f01fc46f72f2d8e2 [file] [log] [blame]
Todd Broch95c22bb2011-02-10 22:45:49 -08001// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <assert.h>
6#include <ftdi.h>
7#include <stdio.h>
8
9#include "ftdi_common.h"
10#include "ftdii2c.h"
11
12static int fi2c_start_bit_cmds(struct fi2c_context *fic) {
13 int i;
14
15 // for now don't allow starts in middle of a command buffer
16 assert(fic->bufcnt == 0);
17
18 // TODO(tbroch) factor in whether its high speed dev or not
19 // guarantee minimum setup time between SDA -> SCL transistions
20 for (i = 0; i < 4; i++) {
21 // SCL & SDA high
22 FI2C_CFG_IO(fic, 0, 0);
23 }
24
25 for (i = 0; i < 4; i++) {
26 // SCL high, SDA low
27 FI2C_CFG_IO(fic, 0, (SDA_POS));
28 }
29
30 // SCL & SDA low
31 FI2C_CFG_IO(fic, 0, (SCL_POS | SDA_POS));
32
33 return FI2C_ERR_NONE;
34}
35
36static int fi2c_stop_bit_cmds(struct fi2c_context *fic) {
37 int i;
38
39 // guarantee minimum setup time between SDA -> SCL transistions
40 for (i = 0; i < 4; i++) {
41 // SCL high, SDA low
42 FI2C_CFG_IO(fic, 0, (SDA_POS));
43 }
44
45 for (i = 0; i < 4; i++) {
46 // SCL & SDA high
47 FI2C_CFG_IO(fic, 0, 0);
48 }
49
50 // SCL & SDA release
51 FI2C_CFG_IO(fic, 0, 0);
52
53 return FI2C_ERR_NONE;
54}
55
56static int fi2c_write_cmds(struct fi2c_context *fic) {
57 int bytes_wrote = 0;
58 int bufcnt = fic->bufcnt;
59
60 fic->bufcnt = 0;
61 bytes_wrote = ftdi_write_data(fic->fc, fic->buf, bufcnt);
62
63 if (bytes_wrote < 0) {
64 ERROR_FTDI("fi2c_write_cmds", fic->fc);
65 return FI2C_ERR_FTDI;
66 } else if (bytes_wrote != bufcnt) {
67 return FI2C_ERR_WRITE;
68 }
69 return FI2C_ERR_NONE;
70}
71
72// TODO(tbroch) can we use the WAIT_ON_x cmds to postpone checking and increase
73// the payload to/from ftdi queues. At the very least use
74// WAIT_ON to h/w check the ack for speeds sake
75static int fi2c_send_byte_and_check(struct fi2c_context *fic, uint8_t data) {
76 int bytes_read;
77 uint8_t rdbuf[1];
78
79 // clk the single byte out
80 FI2C_WBUF(fic, FTDI_CMD_MFE_CLK_BIT_OUT);
81 FI2C_WBUF(fic, 0x07);
82 FI2C_WBUF(fic, data);
83
84 // SCL low, SDA release for Ack
85 FI2C_CFG_IO(fic, 0, SCL_POS);
86
87 // read of the ack (cmd,num of bits)
88 FI2C_WBUF(fic, FTDI_CMD_LRE_CLK_BIT_IN);
89 FI2C_WBUF(fic, 0x00);
90
91 // force rx buffer back to host so you can see ack/noack
92 FI2C_WBUF(fic, SEND_IMMEDIATE);
93
94 CHECK_FI2C(fic, fi2c_write_cmds(fic), "write cmds for ack check\n");
95 prn_dbg("bufcnt after write = %d\n", fic->bufcnt);
96
97 // TODO(tbroch) this is s/w ACK should be doable via h/w WAIT_ON_x
98 bytes_read = ftdi_read_data(fic->fc, rdbuf, 1);
Todd Broch95c22bb2011-02-10 22:45:49 -080099 if (bytes_read < 0) {
100 ERROR_FTDI("read of ack", fic->fc);
101 return FI2C_ERR_FTDI;
102 }
103 if (bytes_read != 1) {
Todd Broch7381c312011-03-14 10:52:18 -0700104 prn_error("bytes read %d != 1\n", bytes_read);
Todd Broch95c22bb2011-02-10 22:45:49 -0800105 return FI2C_ERR_READ;
106 } else {
107 if ((rdbuf[0] & 0x80) != 0x0) {
Todd Broch7381c312011-03-14 10:52:18 -0700108 prn_error("ack read 0x%02x != 0x0\n", (rdbuf[0] & 0x80));
Todd Broch95c22bb2011-02-10 22:45:49 -0800109 return FI2C_ERR_ACK;
110 }
111 prn_dbg("saw the ack 0x%02x\n", rdbuf[0]);
112 }
113
114 // TODO(tbroch) : shouldn't need to pull SDA high here but get strange results
115 // otherwise. Needs investigation
116 // SCL low, SDA high
117 FI2C_CFG_IO(fic, SDA_POS, (SCL_POS | SDA_POS));
118 return FI2C_ERR_NONE;
119}
120
121static int fi2c_send_slave(struct fi2c_context *fic, int read) {
122 return fi2c_send_byte_and_check(fic, (fic->slv<<1) | (read ? 0x1 : 0x0));
123}
124
125static int fi2c_wr(struct fi2c_context *fic, uint8_t *wbuf, int wcnt) {
126 int i;
127
128 for (i = 0; i < wcnt; i++) {
129 CHECK_FI2C(fic, fi2c_send_byte_and_check(fic, wbuf[i]),
130 "wr byte look for ack\n");
131 if (fic->error)
132 return fic->error;
133 }
134 return FI2C_ERR_NONE;
135}
136
137static int fi2c_rd(struct fi2c_context *fic, uint8_t *rbuf, int rcnt) {
138 int i;
139
140 for (i = 0; i < rcnt; i++) {
141 // SCL low
142 FI2C_CFG_IO(fic, 0, SCL_POS);
143
144 FI2C_WBUF(fic, FTDI_CMD_MRE_CLK_BYTE_IN);
145 FI2C_WBUF(fic, 0x00);
146 FI2C_WBUF(fic, 0x00);
147
148 if (i == rcnt - 1) {
149 // last byte ... send NACK
150 FI2C_CFG_IO(fic, 0, (SCL_POS));
151 FI2C_WBUF(fic, FTDI_CMD_MFE_CLK_BIT_OUT);
152 FI2C_WBUF(fic, 0x0);
153 FI2C_WBUF(fic, 0xff);
154 } else {
155 // send ACK
156 FI2C_CFG_IO(fic, 0, (SCL_POS | SDA_POS ));
157 FI2C_WBUF(fic, FTDI_CMD_MFE_CLK_BIT_OUT);
158 FI2C_WBUF(fic, 0x0);
159 FI2C_WBUF(fic, 0x0);
160 }
161 }
162 FI2C_WBUF(fic, SEND_IMMEDIATE);
163 CHECK_FI2C(fic, fi2c_write_cmds(fic), "FTDI cmd write for read\n");
164 if (fic->error)
165 return fic->error;
166
167 int bytes_read;
168 if ((bytes_read = ftdi_read_data(fic->fc, rbuf, rcnt)) != rcnt) {
169 if (bytes_read < 0) {
170 ERROR_FTDI("FTDI read bytes", fic->fc);
171 } else {
172 prn_error("ftdi bytes_read %d != %d expected\n", bytes_read, rcnt);
173 }
174 return FI2C_ERR_READ;
175 }
176 return FI2C_ERR_NONE;
177}
178
179int fi2c_init(struct fi2c_context *fic, struct ftdi_context *fc) {
180 assert(fic);
181 memset(fic, 0, sizeof(*fic));
182
183 fic->fc = fc;
184 fic->fc->usb_read_timeout = 10000;
185 if ((fic->buf = malloc(FI2C_BUF_SIZE)) != NULL) {
186 fic->bufsize = FI2C_BUF_SIZE;
187 }
188 fic->bufcnt = 0;
189
190 // init all inputs
191 fic->gpio.direction = 0;
192 fic->gpio.value = 0;
193 fic->gpio.mask = ~(SCL_POS | SDA_POS | SDB_POS);
194 fic->error = FI2C_ERR_NONE;
195
196 return FI2C_ERR_NONE;
197}
198
199int fi2c_open(struct fi2c_context *fic, struct ftdi_common_args *fargs) {
200
201 ftdi_set_interface(fic->fc, fargs->interface);
202 if (!IS_FTDI_OPEN(fic->fc)) {
203 int rv = ftdi_usb_open(fic->fc, fargs->vendor_id, fargs->product_id);
204 if (rv < 0 && rv != -5) {
205 ERROR_FTDI("Opening usb connection", fic->fc);
206 return rv;
207 }
208 }
209 if (!fcom_is_mpsse(fic->fc, fargs)) {
210 prn_error("ftdi device / interface doesn't support MPSSE\n");
211 return FI2C_ERR_FTDI;
212 }
213 return fcom_cfg(fic->fc, fargs->interface, BITMODE_MPSSE, 0);
214}
215
216int fi2c_setclock(struct fi2c_context *fic, uint32_t clk) {
217 uint8_t buf[3] = { 0, 0, 0 };
218
219
220
221 buf[0] = FTDI_CMD_3PHASE;
222 CHECK_FTDI(ftdi_write_data(fic->fc, buf, 1), "Set 3-phase clocking",
223 fic->fc);
224 if (clk > FTDI_CLK_MAX_X5 || clk < FTDI_CLK_MIN) {
225 return FI2C_ERR_CLK;
226 }
227 if (clk > FTDI_CLK_MAX_X5) {
228 buf[0] = FTDI_CMD_X5_OFF;
229 CHECK_FTDI(ftdi_write_data(fic->fc, buf, 1), "Set master clock 60mhz",
230 fic->fc);
231 }
232 // 1.5 due to 3-phase requirement
233 int div = DIV_VALUE((clk*1.5));
234 if (!div) {
235 prn_error("Unable to determine clock divisor\n");
236 return FI2C_ERR_CLK;
237 }
238 buf[0] = TCK_DIVISOR;
239 buf[1] = (div >> 0) & 0xFF;
240 buf[2] = (div >> 8) & 0xFF;
241 CHECK_FTDI(ftdi_write_data(fic->fc, buf, 3), "Set clk div", fic->fc);
242 return FI2C_ERR_NONE;
243}
244
245int fi2c_reset(struct fi2c_context *fic) {
246 CHECK_FI2C(fic, fi2c_start_bit_cmds(fic), "Start sent as reset\n");
247 CHECK_FI2C(fic, fi2c_write_cmds(fic), "FTDI write cmds\n");
248 fic->error = FI2C_ERR_NONE;
249 return fic->error;
250}
251
252int fi2c_wr_rd(struct fi2c_context *fic, uint8_t *wbuf, int wcnt,
253 uint8_t *rbuf, int rcnt) {
Todd Broch7381c312011-03-14 10:52:18 -0700254 int err;
255 static int retry_count;
256
257 retry:
Todd Broch95c22bb2011-02-10 22:45:49 -0800258 if (wcnt && wbuf) {
Todd Broch7381c312011-03-14 10:52:18 -0700259#ifdef DEBUG
260 printf("begin write of: ");
261 int i;
262 for (i = 0; i < wcnt; i++) {
263 printf("0x%02x ", wbuf[i]);
264 }
265 printf("\n");
266#endif
Todd Broch95c22bb2011-02-10 22:45:49 -0800267 CHECK_FI2C(fic, fi2c_start_bit_cmds(fic), "(WR) Start bit\n");
Todd Broch7381c312011-03-14 10:52:18 -0700268 err = fi2c_send_slave(fic, 0);
269 if (err == FI2C_ERR_READ) {
270 retry_count++;
271 goto retry;
272 }
273 if (!fic->error && !err) {
274 err = fi2c_wr(fic, wbuf, wcnt);
275 if (err == FI2C_ERR_READ) {
276 retry_count++;
277 goto retry;
278 }
Todd Broch95c22bb2011-02-10 22:45:49 -0800279 CHECK_FI2C(fic, fi2c_stop_bit_cmds(fic), "(WR) Stop bit\n");
280 CHECK_FI2C(fic, fi2c_write_cmds(fic), "(WR) FTDI write cmds\n");
281 }
282 }
283 if (rcnt && rbuf && !fic->error) {
284 prn_dbg("begin read\n");
285 CHECK_FI2C(fic, fi2c_start_bit_cmds(fic), "(RD) Start bit\n");
Todd Broch7381c312011-03-14 10:52:18 -0700286 err = fi2c_send_slave(fic, 1);
287 if (err == FI2C_ERR_READ) {
288 retry_count++;
289 goto retry;
Todd Broch95c22bb2011-02-10 22:45:49 -0800290 }
Todd Broch7381c312011-03-14 10:52:18 -0700291 CHECK_FI2C(fic, fi2c_rd(fic, rbuf, rcnt), "(RD) Payload\n");
292#ifdef DEBUG
293 printf("end read: ");
294 int i;
295 for (i = 0; i < rcnt; i++) {
296 printf("0x%02x ", rbuf[i]);
297 }
298 printf("\n");
299#endif
Todd Broch95c22bb2011-02-10 22:45:49 -0800300 }
301 // TODO(tbroch) debug why this is necessary. W/o I get sporadic
302 // ftdi_usb_read_data failures. Might be able to remedy by looking at
303 // error codes from ftdi_read/write ( -666 ) or errno -16 (EBUSY)
304 // NOTE, removing exposes bug on linux w/ bad results
305 CHECK_FTDI(ftdi_usb_purge_tx_buffer(fic->fc), "Purge tx buf", fic->fc);
Todd Broch7381c312011-03-14 10:52:18 -0700306 prn_dbg("done. Error = %d, Retry count = %d\n", fic->error, retry_count);
Todd Broch95c22bb2011-02-10 22:45:49 -0800307 return fic->error;
308}
309
310int fi2c_close(struct fi2c_context *fic) {
311 CHECK_FTDI(ftdi_usb_close(fic->fc), "fic close", fic->fc);
312 ftdi_deinit(fic->fc);
313 return FI2C_ERR_NONE;
314}
315