blob: 36b8969ec46ab0ea06d62ce139ed2142b7dafec6 [file] [log] [blame]
Paul Fox05dfbe62009-06-16 21:08:06 +00001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2009 Paul Fox <pgf@laptop.org>
5 * Copyright (C) 2009 Carl-Daniel Hailfinger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <stdio.h>
22#include <stdint.h>
23#include <string.h>
24#include <stdlib.h>
25#include "flash.h"
26#include "spi.h"
27
28#if FT2232_SPI_SUPPORT == 1
29
30#include <ftdi.h>
31
32/* the 'H' chips can run internally at either 12Mhz or 60Mhz.
33 * the non-H chips can only run at 12Mhz. */
34#define CLOCK_5X 1
35
36/* in either case, the divisor is a simple integer clock divider.
37 * if CLOCK_5X is set, this divisor divides 30Mhz, else it
38 * divides 6Mhz */
39#define DIVIDE_BY 3 // e.g. '3' will give either 10Mhz or 2Mhz spi clock
40
41
42static struct ftdi_context ftdic_context;
43
44int send_buf(struct ftdi_context *ftdic, const unsigned char *buf, int size)
45{
46 int r;
47 r = ftdi_write_data(ftdic, (unsigned char *) buf, size);
48 if (r < 0) {
49 fprintf(stderr, "ftdi_write_data: %d, %s\n", r,
50 ftdi_get_error_string(ftdic));
51 return 1;
52 }
53 return 0;
54}
55
56int get_buf(struct ftdi_context *ftdic, const unsigned char *buf, int size)
57{
58 int r;
59 r = ftdi_read_data(ftdic, (unsigned char *) buf, size);
60 if (r < 0) {
61 fprintf(stderr, "ftdi_read_data: %d, %s\n", r,
62 ftdi_get_error_string(ftdic));
63 return 1;
64 }
65 return 0;
66}
67
68int ft2232_spi_init(void)
69{
70 int f;
71 struct ftdi_context *ftdic = &ftdic_context;
72 unsigned char buf[512];
73 unsigned char port_val = 0;
74
75
76 if (ftdi_init(ftdic) < 0) {
77 fprintf(stderr, "ftdi_init failed\n");
78 return EXIT_FAILURE;
79 }
80
81 // f = ftdi_usb_open(ftdic, 0x0403, 0x6010); // FT2232
82 f = ftdi_usb_open(ftdic, 0x0403, 0x6011); // FT4232
83
84 if (f < 0 && f != -5) {
85 fprintf(stderr, "Unable to open ftdi device: %d (%s)\n", f,
86 ftdi_get_error_string(ftdic));
87 exit(-1);
88 }
89
90 if (ftdi_set_interface(ftdic, INTERFACE_B) < 0) {
91 fprintf(stderr, "Unable to select FT2232 channel B: %s\n",
92 ftdic->error_str);
93 }
94
95 if (ftdi_usb_reset(ftdic) < 0) {
96 fprintf(stderr, "Unable to reset ftdi device\n");
97 }
98
99 if (ftdi_set_latency_timer(ftdic, 2) < 0) {
100 fprintf(stderr, "Unable to set latency timer\n");
101 }
102
103 if (ftdi_write_data_set_chunksize(ftdic, 512)) {
104 fprintf(stderr, "Unable to set chunk size\n");
105 }
106
107 if (ftdi_set_bitmode(ftdic, 0x00, 2) < 0) {
108 fprintf(stderr, "Unable to set bitmode\n");
109 }
110
111#if CLOCK_5X
112 printf_debug("Disable divide-by-5 front stage\n");
113 buf[0] = 0x8a; /* disable divide-by-5 */
114 if (send_buf(ftdic, buf, 1))
115 return -1;
116#define MPSSE_CLK 60.0
117
118#else
119
120#define MPSSE_CLK 12.0
121
122#endif
123 printf_debug("Set clock divisor\n");
124 buf[0] = 0x86; /* command "set divisor" */
125 /* valueL/valueH are (desired_divisor - 1) */
126 buf[1] = (DIVIDE_BY-1) & 0xff;
127 buf[2] = ((DIVIDE_BY-1) >> 8) & 0xff;
128 if (send_buf(ftdic, buf, 3))
129 return -1;
130
131 printf("SPI clock is %fMHz\n",
132 (double)(MPSSE_CLK / (((DIVIDE_BY-1) + 1) * 2)));
133
134 /* Disconnect TDI/DO to TDO/DI for Loopback */
135 printf_debug("No loopback of tdi/do tdo/di\n");
136 buf[0] = 0x85;
137 if (send_buf(ftdic, buf, 1))
138 return -1;
139
140 printf_debug("Set data bits\n");
141 /* Set data bits low-byte command:
142 * value: 0x08 CS=high, DI=low, DO=low, SK=low
143 * dir: 0x0b CS=output, DI=input, DO=output, SK=output
144 */
145#define CS_BIT 0x08
146
147 buf[0] = SET_BITS_LOW;
148 buf[1] = (port_val = CS_BIT);
149 buf[2] = 0x0b;
150 if (send_buf(ftdic, buf, 3))
151 return -1;
152
153 printf_debug("\nft2232 chosen\n");
154
155 buses_supported = CHIP_BUSTYPE_SPI;
156 spi_controller = SPI_CONTROLLER_FT2232;
157
158 return 0;
159}
160
161int ft2232_spi_command(unsigned int writecnt, unsigned int readcnt,
162 const unsigned char *writearr, unsigned char *readarr)
163{
164 struct ftdi_context *ftdic = &ftdic_context;
165 static unsigned char *buf = NULL;
166 unsigned char port_val = 0;
167 int i, ret = 0;
168
169 buf = realloc(buf, writecnt + readcnt + 100);
170 if (!buf) {
171 fprintf(stderr, "Out of memory!\n");
172 exit(1);
173 }
174
175 i = 0;
176
177 /* minimize USB transfers by packing as many commands
178 * as possible together. if we're not expecting to
179 * read, we can assert CS, write, and deassert CS all
180 * in one shot. if reading, we do three separate
181 * operations. */
182 printf_debug("Assert CS#\n");
183 buf[i++] = SET_BITS_LOW;
184 buf[i++] = (port_val &= ~CS_BIT);
185 buf[i++] = 0x0b;
186
187 if (writecnt) {
188 buf[i++] = 0x11;
189 buf[i++] = (writecnt - 1) & 0xff;
190 buf[i++] = ((writecnt - 1) >> 8) & 0xff;
191 memcpy(buf+i, writearr, writecnt);
192 i += writecnt;
193 }
194
195 /* optionally terminate this batch of commands with a
196 * read command, then do the fetch of the results.
197 */
198 if (readcnt) {
199 buf[i++] = 0x20;
200 buf[i++] = (readcnt - 1) & 0xff;
201 buf[i++] = ((readcnt - 1) >> 8) & 0xff;
202 ret = send_buf(ftdic, buf, i);
203 i = 0;
204 if (ret) goto deassert_cs;
205
206 /* FIXME: This is unreliable. There's no guarantee that we read
207 * the response directly after sending the read command.
208 * We may be scheduled out etc.
209 */
210 ret = get_buf(ftdic, readarr, readcnt);
211
212 }
213
Uwe Hermann1432a602009-06-28 23:26:37 +0000214deassert_cs:
Paul Fox05dfbe62009-06-16 21:08:06 +0000215 printf_debug("De-assert CS#\n");
216 buf[i++] = SET_BITS_LOW;
217 buf[i++] = (port_val |= CS_BIT);
218 buf[i++] = 0x0b;
219 if (send_buf(ftdic, buf, i))
220 return -1;
221
222 return ret;
223}
224
225int ft2232_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len)
226{
227 /* Maximum read length is 64k bytes. */
228 return spi_read_chunked(flash, buf, start, len, 64 * 1024);
229}
230
231int ft2232_spi_write_256(struct flashchip *flash, uint8_t *buf)
232{
233 int total_size = 1024 * flash->total_size;
234 int i;
235
236 printf_debug("total_size is %d\n", total_size);
237 for (i = 0; i < total_size; i += 256) {
238 int l, r;
239 if (i + 256 <= total_size)
240 l = 256;
241 else
242 l = total_size - i;
243
244 spi_write_enable();
245 if ((r = spi_nbyte_program(i, &buf[i], l))) {
246 fprintf(stderr, "%s: write fail %d\n", __FUNCTION__, r);
247 // spi_write_disable(); chip does this for us
248 return 1;
249 }
250
251 while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
252 /* loop */;
253 }
254 // spi_write_disable(); chip does this for us
255
256 return 0;
257}
258
259#else
260int ft2232_spi_init(void)
261{
262 fprintf(stderr, "FT2232 SPI support was not compiled in\n");
263 exit(1);
264}
265
266int ft2232_spi_command(unsigned int writecnt, unsigned int readcnt,
267 const unsigned char *writearr, unsigned char *readarr)
268{
269 fprintf(stderr, "FT2232 SPI support was not compiled in\n");
270 exit(1);
271}
272
273int ft2232_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len)
274{
275 fprintf(stderr, "FT2232 SPI support was not compiled in\n");
276 exit(1);
277}
278
279int ft2232_spi_write_256(struct flashchip *flash, uint8_t *buf)
280{
281 fprintf(stderr, "FT2232 SPI support was not compiled in\n");
282 exit(1);
283}
284#endif