blob: 53e78d340256a8b6f9106361f4c82aa39a6daaef [file] [log] [blame]
hailfingerf31da3d2009-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>
hailfinger39d159a2010-05-21 23:09:42 +00005 * Copyright (C) 2009, 2010 Carl-Daniel Hailfinger
hailfingerf31da3d2009-06-16 21:08:06 +00006 *
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.
hailfingerf31da3d2009-06-16 21:08:06 +000015 */
16
hailfinger90c7d542010-05-31 15:27:27 +000017#if CONFIG_FT2232_SPI == 1
hailfingerd9dcfbd2009-08-19 13:27:58 +000018
hailfingerf31da3d2009-06-16 21:08:06 +000019#include <stdio.h>
Edward O'Callaghan2068b922019-08-21 16:43:26 +100020#include <strings.h>
hailfingerf31da3d2009-06-16 21:08:06 +000021#include <string.h>
22#include <stdlib.h>
hailfingere98628b2009-07-01 00:02:23 +000023#include <ctype.h>
hailfingerf31da3d2009-06-16 21:08:06 +000024#include "flash.h"
hailfinger428f6852010-07-27 22:41:39 +000025#include "programmer.h"
hailfingerf31da3d2009-06-16 21:08:06 +000026#include "spi.h"
hailfingerf31da3d2009-06-16 21:08:06 +000027#include <ftdi.h>
28
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +110029/* This is not defined in libftdi.h <0.20 (c7e4c09e68cfa6f5e112334aa1b3bb23401c8dc7 to be exact).
30 * Some tests indicate that his is the only change that it is needed to support the FT232H in flashrom. */
31#if !defined(HAVE_FT232H)
32#define TYPE_232H 6
33#endif
34
uwed4ab19b2011-10-14 20:33:14 +000035/* Please keep sorted by vendor ID, then device ID. */
36
uwe3dae6872010-07-29 19:57:55 +000037#define FTDI_VID 0x0403
38#define FTDI_FT2232H_PID 0x6010
39#define FTDI_FT4232H_PID 0x6011
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +110040#define FTDI_FT232H_PID 0x6014
uwed4ab19b2011-10-14 20:33:14 +000041#define TIAO_TUMPA_PID 0x8a98
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +110042#define TIAO_TUMPA_LITE_PID 0x8a99
uwe3dae6872010-07-29 19:57:55 +000043#define AMONTEC_JTAGKEY_PID 0xCFF8
hailfinger888410e2010-07-29 15:54:53 +000044
uwe64e8d6f2011-10-20 23:14:10 +000045#define GOEPEL_VID 0x096C
46#define GOEPEL_PICOTAP_PID 0x1449
47
hailfingerce670612010-11-10 03:26:57 +000048#define FIC_VID 0x1457
49#define OPENMOKO_DBGBOARD_PID 0x5118
50
stefanct93481112011-06-11 12:21:37 +000051#define OLIMEX_VID 0x15BA
52#define OLIMEX_ARM_OCD_PID 0x0003
53#define OLIMEX_ARM_TINY_PID 0x0004
54#define OLIMEX_ARM_OCD_H_PID 0x002B
55#define OLIMEX_ARM_TINY_H_PID 0x002A
56
Todd Broch7aff3df2011-08-23 13:41:53 -070057#define GOOGLE_VID 0x18D1
58#define GOOGLE_SERVO_PID 0x5001
Todd Broch97f259f2012-04-03 15:52:14 -070059#define GOOGLE_SERVO_V2_PID0 0x5002
60#define GOOGLE_SERVO_V2_PID1 0x5003
Todd Broch7aff3df2011-08-23 13:41:53 -070061
Nikolai Artemievc347a852020-04-29 12:17:08 +100062const struct dev_entry devs_ft2232spi[] = {
uwe3dae6872010-07-29 19:57:55 +000063 {FTDI_VID, FTDI_FT2232H_PID, OK, "FTDI", "FT2232H"},
64 {FTDI_VID, FTDI_FT4232H_PID, OK, "FTDI", "FT4232H"},
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +110065 {FTDI_VID, FTDI_FT232H_PID, OK, "FTDI", "FT232H"},
uwed4ab19b2011-10-14 20:33:14 +000066 {FTDI_VID, TIAO_TUMPA_PID, OK, "TIAO", "USB Multi-Protocol Adapter"},
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +110067 {FTDI_VID, TIAO_TUMPA_LITE_PID, OK, "TIAO", "USB Multi-Protocol Adapter Lite"},
uwe3dae6872010-07-29 19:57:55 +000068 {FTDI_VID, AMONTEC_JTAGKEY_PID, OK, "Amontec", "JTAGkey"},
uwe64e8d6f2011-10-20 23:14:10 +000069 {GOEPEL_VID, GOEPEL_PICOTAP_PID, OK, "GOEPEL", "PicoTAP"},
Todd Broch7aff3df2011-08-23 13:41:53 -070070 {GOOGLE_VID, GOOGLE_SERVO_PID, OK, "Google", "Servo"},
Todd Broch97f259f2012-04-03 15:52:14 -070071 {GOOGLE_VID, GOOGLE_SERVO_V2_PID0, OK, "Google", "Servo V2 Legacy"},
72 {GOOGLE_VID, GOOGLE_SERVO_V2_PID1, OK, "Google", "Servo V2"},
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +110073 {FIC_VID, OPENMOKO_DBGBOARD_PID, OK, "FIC", "OpenMoko Neo1973 Debug board (V2+)"},
74 {OLIMEX_VID, OLIMEX_ARM_OCD_PID, OK, "Olimex", "ARM-USB-OCD"},
75 {OLIMEX_VID, OLIMEX_ARM_TINY_PID, OK, "Olimex", "ARM-USB-TINY"},
76 {OLIMEX_VID, OLIMEX_ARM_OCD_H_PID, OK, "Olimex", "ARM-USB-OCD-H"},
77 {OLIMEX_VID, OLIMEX_ARM_TINY_H_PID, OK, "Olimex", "ARM-USB-TINY-H"},
78
Patrick Georgi8ddfee92017-03-20 14:54:28 +010079 {0},
hailfinger888410e2010-07-29 15:54:53 +000080};
81
Nikolai Artemiev985f1952020-01-20 16:33:30 +110082#define DEFAULT_DIVISOR 2
hailfingerf31da3d2009-06-16 21:08:06 +000083
uweb34ec9f2009-10-01 18:40:02 +000084#define BITMODE_BITBANG_NORMAL 1
85#define BITMODE_BITBANG_SPI 2
hailfingerf31da3d2009-06-16 21:08:06 +000086
Nikolai Artemiev0a635262020-02-11 13:49:52 +110087/* The variables cs_bits and pindir store the values for the "set data bits low byte" MPSSE command that
88 * sets the initial state and the direction of the I/O pins. The pin offsets are as follows:
sibradzic419c86f2020-02-04 18:24:58 +090089 * TCK/SK is bit 0.
90 * TDI/DO is bit 1.
91 * TDO/DI is bit 2.
92 * TMS/CS is bit 3.
93 * GPIOL0 is bit 4.
94 * GPIOL1 is bit 5.
95 * GPIOL2 is bit 6.
96 * GPIOL3 is bit 7.
97 *
98 * The pin signal direction bit offsets follow the same order; 0 means that
99 * pin at the matching bit index is an input, 1 means pin is an output.
Nikolai Artemiev0a635262020-02-11 13:49:52 +1100100 *
101 * The default values (set below) are used for most devices:
hailfinger888410e2010-07-29 15:54:53 +0000102 * value: 0x08 CS=high, DI=low, DO=low, SK=low
103 * dir: 0x0b CS=output, DI=input, DO=output, SK=output
hailfinger888410e2010-07-29 15:54:53 +0000104 */
uwe3dae6872010-07-29 19:57:55 +0000105static uint8_t cs_bits = 0x08;
106static uint8_t pindir = 0x0b;
hailfingerf31da3d2009-06-16 21:08:06 +0000107static struct ftdi_context ftdic_context;
108
hailfinger888410e2010-07-29 15:54:53 +0000109static const char *get_ft2232_devicename(int ft2232_vid, int ft2232_type)
110{
111 int i;
uwe3dae6872010-07-29 19:57:55 +0000112 for (i = 0; devs_ft2232spi[i].vendor_name != NULL; i++) {
hailfinger888410e2010-07-29 15:54:53 +0000113 if ((devs_ft2232spi[i].device_id == ft2232_type)
114 && (devs_ft2232spi[i].vendor_id == ft2232_vid))
115 return devs_ft2232spi[i].device_name;
116 }
117 return "unknown device";
118}
119
120static const char *get_ft2232_vendorname(int ft2232_vid, int ft2232_type)
121{
122 int i;
uwe3dae6872010-07-29 19:57:55 +0000123 for (i = 0; devs_ft2232spi[i].vendor_name != NULL; i++) {
124 if ((devs_ft2232spi[i].device_id == ft2232_type)
125 && (devs_ft2232spi[i].vendor_id == ft2232_vid))
126 return devs_ft2232spi[i].vendor_name;
127 }
128 return "unknown vendor";
hailfinger888410e2010-07-29 15:54:53 +0000129}
130
uwe3dae6872010-07-29 19:57:55 +0000131static int send_buf(struct ftdi_context *ftdic, const unsigned char *buf,
132 int size)
hailfingerf31da3d2009-06-16 21:08:06 +0000133{
134 int r;
135 r = ftdi_write_data(ftdic, (unsigned char *) buf, size);
136 if (r < 0) {
snelson93932992010-01-10 01:08:37 +0000137 msg_perr("ftdi_write_data: %d, %s\n", r,
hailfingerf31da3d2009-06-16 21:08:06 +0000138 ftdi_get_error_string(ftdic));
139 return 1;
140 }
141 return 0;
142}
143
uwe3dae6872010-07-29 19:57:55 +0000144static int get_buf(struct ftdi_context *ftdic, const unsigned char *buf,
145 int size)
hailfingerf31da3d2009-06-16 21:08:06 +0000146{
147 int r;
hailfinger694faa22010-11-10 03:10:41 +0000148
149 while (size > 0) {
150 r = ftdi_read_data(ftdic, (unsigned char *) buf, size);
151 if (r < 0) {
152 msg_perr("ftdi_read_data: %d, %s\n", r,
153 ftdi_get_error_string(ftdic));
154 return 1;
155 }
156 buf += r;
157 size -= r;
hailfingerf31da3d2009-06-16 21:08:06 +0000158 }
159 return 0;
160}
161
Nikolai Artemiev0a635262020-02-11 13:49:52 +1100162static int ft2232_spi_send_command(const struct flashctx *flash,
163 unsigned int writecnt, unsigned int readcnt,
164 const unsigned char *writearr,
165 unsigned char *readarr);
mkarcherd264e9e2011-05-11 17:07:07 +0000166
Patrick Georgif4f1e2f2017-03-10 17:38:40 +0100167static const struct spi_master spi_master_ft2232 = {
Edward O'Callaghana6673bd2019-06-24 15:22:28 +1000168 .features = SPI_MASTER_4BA,
uwe8d342eb2011-07-28 08:13:25 +0000169 .max_data_read = 64 * 1024,
170 .max_data_write = 256,
171 .command = ft2232_spi_send_command,
172 .multicommand = default_spi_send_multicommand,
173 .read = default_spi_read,
174 .write_256 = default_spi_write_256,
mkarcherd264e9e2011-05-11 17:07:07 +0000175};
176
uwe56199592011-07-21 09:18:18 +0000177/* Returns 0 upon success, a negative number upon errors. */
David Hendricksac1d25c2016-08-09 17:00:58 -0700178int ft2232_spi_init(void)
hailfingerf31da3d2009-06-16 21:08:06 +0000179{
Nikolai Artemiev985f1952020-01-20 16:33:30 +1100180 int ret = 0;
hailfingerf31da3d2009-06-16 21:08:06 +0000181 struct ftdi_context *ftdic = &ftdic_context;
182 unsigned char buf[512];
hailfinger888410e2010-07-29 15:54:53 +0000183 int ft2232_vid = FTDI_VID;
184 int ft2232_type = FTDI_FT4232H_PID;
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +1100185 int channel_count = 4; /* Stores the number of channels of the device. */
186 enum ftdi_interface ft2232_interface = INTERFACE_A;
Nikolai Artemiev985f1952020-01-20 16:33:30 +1100187 /*
188 * The 'H' chips can run with an internal clock of either 12 MHz or 60 MHz,
189 * but the non-H chips can only run at 12 MHz. We disable the divide-by-5
190 * prescaler on 'H' chips so they run at 60MHz.
191 */
192 uint8_t clock_5x = 1;
193 /* In addition to the prescaler mentioned above there is also another
194 * configurable one on all versions of the chips. Its divisor div can be
195 * set by a 16 bit value x according to the following formula:
196 * div = (1 + x) * 2 <-> x = div / 2 - 1
197 * Hence the expressible divisors are all even numbers between 2 and
198 * 2^17 (=131072) resulting in SCK frequencies of 6 MHz down to about
199 * 92 Hz for 12 MHz inputs and 30 MHz down to about 458 Hz for 60 MHz
200 * inputs.
201 */
Nikolai Artemiev985f1952020-01-20 16:33:30 +1100202 uint32_t divisor = DEFAULT_DIVISOR;
203 int f;
hailfinger1ef766d2010-07-06 09:55:48 +0000204 char *arg;
hailfinger81f90f22010-11-10 03:18:41 +0000205 double mpsse_clk;
hailfinger1ef766d2010-07-06 09:55:48 +0000206
hailfingerddeb4ac2010-07-08 10:13:37 +0000207 arg = extract_programmer_param("type");
hailfinger1ef766d2010-07-06 09:55:48 +0000208 if (arg) {
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +1100209 if (!strcasecmp(arg, "2232H")) {
hailfinger888410e2010-07-29 15:54:53 +0000210 ft2232_type = FTDI_FT2232H_PID;
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +1100211 channel_count = 2;
212 } else if (!strcasecmp(arg, "4232H")) {
hailfinger888410e2010-07-29 15:54:53 +0000213 ft2232_type = FTDI_FT4232H_PID;
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +1100214 channel_count = 4;
215 } else if (!strcasecmp(arg, "232H")) {
216 ft2232_type = FTDI_FT232H_PID;
217 channel_count = 1;
218 } else if (!strcasecmp(arg, "jtagkey")) {
hailfinger888410e2010-07-29 15:54:53 +0000219 ft2232_type = AMONTEC_JTAGKEY_PID;
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +1100220 channel_count = 2;
221 /* JTAGkey(2) needs to enable its output via Bit4 / GPIOL0
222 * value: 0x18 OE=high, CS=high, DI=low, DO=low, SK=low
223 * dir: 0x1b OE=output, CS=output, DI=input, DO=output, SK=output */
hailfinger888410e2010-07-29 15:54:53 +0000224 cs_bits = 0x18;
uwe3dae6872010-07-29 19:57:55 +0000225 pindir = 0x1b;
uwe64e8d6f2011-10-20 23:14:10 +0000226 } else if (!strcasecmp(arg, "picotap")) {
227 ft2232_vid = GOEPEL_VID;
228 ft2232_type = GOEPEL_PICOTAP_PID;
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +1100229 channel_count = 2;
uwed4ab19b2011-10-14 20:33:14 +0000230 } else if (!strcasecmp(arg, "tumpa")) {
231 /* Interface A is SPI1, B is SPI2. */
232 ft2232_type = TIAO_TUMPA_PID;
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +1100233 channel_count = 2;
234 } else if (!strcasecmp(arg, "tumpalite")) {
235 /* Only one channel is used on lite edition */
236 ft2232_type = TIAO_TUMPA_LITE_PID;
237 channel_count = 1;
stefanct90aefe82011-08-12 01:19:32 +0000238 } else if (!strcasecmp(arg, "busblaster")) {
239 /* In its default configuration it is a jtagkey clone */
240 ft2232_type = FTDI_FT2232H_PID;
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +1100241 channel_count = 2;
stefanct90aefe82011-08-12 01:19:32 +0000242 cs_bits = 0x18;
243 pindir = 0x1b;
hailfingerce670612010-11-10 03:26:57 +0000244 } else if (!strcasecmp(arg, "openmoko")) {
245 ft2232_vid = FIC_VID;
246 ft2232_type = OPENMOKO_DBGBOARD_PID;
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +1100247 channel_count = 2;
stefanct93481112011-06-11 12:21:37 +0000248 } else if (!strcasecmp(arg, "arm-usb-ocd")) {
249 ft2232_vid = OLIMEX_VID;
250 ft2232_type = OLIMEX_ARM_OCD_PID;
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +1100251 channel_count = 2;
252 /* arm-usb-ocd(-h) has an output buffer that needs to be enabled by pulling ADBUS4 low.
253 * value: 0x08 #OE=low, CS=high, DI=low, DO=low, SK=low
254 * dir: 0x1b #OE=output, CS=output, DI=input, DO=output, SK=output */
Paul Fertser80ed25d2016-07-29 15:31:03 -0700255 cs_bits = 0x08;
256 pindir = 0x1b;
stefanct93481112011-06-11 12:21:37 +0000257 } else if (!strcasecmp(arg, "arm-usb-tiny")) {
258 ft2232_vid = OLIMEX_VID;
259 ft2232_type = OLIMEX_ARM_TINY_PID;
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +1100260 channel_count = 2;
stefanct93481112011-06-11 12:21:37 +0000261 } else if (!strcasecmp(arg, "arm-usb-ocd-h")) {
262 ft2232_vid = OLIMEX_VID;
263 ft2232_type = OLIMEX_ARM_OCD_H_PID;
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +1100264 channel_count = 2;
265 /* See arm-usb-ocd */
Paul Fertser80ed25d2016-07-29 15:31:03 -0700266 cs_bits = 0x08;
267 pindir = 0x1b;
stefanct93481112011-06-11 12:21:37 +0000268 } else if (!strcasecmp(arg, "arm-usb-tiny-h")) {
269 ft2232_vid = OLIMEX_VID;
270 ft2232_type = OLIMEX_ARM_TINY_H_PID;
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +1100271 channel_count = 2;
Edward O'Callaghanb9a1dcf2020-03-02 17:14:14 +1100272 } else if (!strcasecmp(arg, "google-servo")) {
273 ft2232_vid = GOOGLE_VID;
274 ft2232_type = GOOGLE_SERVO_PID;
275 channel_count = 2;
276 } else if (!strcasecmp(arg, "google-servo-v2")) {
277 ft2232_vid = GOOGLE_VID;
278 ft2232_type = GOOGLE_SERVO_V2_PID1;
279 channel_count = 2;
280 /* Default divisor is too fast, and chip ID fails */
281 divisor = 6;
282 } else if (!strcasecmp(arg, "google-servo-v2-legacy")) {
283 ft2232_vid = GOOGLE_VID;
284 ft2232_type = GOOGLE_SERVO_V2_PID0;
285 channel_count = 2;
286 /* vv WARNING: deprecated vv */
Todd Broch7aff3df2011-08-23 13:41:53 -0700287 } else if (!strcasecmp(arg, "servo")) {
288 ft2232_vid = GOOGLE_VID;
289 ft2232_type = GOOGLE_SERVO_PID;
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +1100290 channel_count = 2;
Nicolas Boichatd520d3b2020-05-18 08:26:20 +0800291 msg_pwarn("Warning: Use 'google-servo' instead!\n");
Todd Broche1e13ec2012-01-17 09:32:13 -0800292 } else if (!strcasecmp(arg, "servo-v2")) {
293 ft2232_vid = GOOGLE_VID;
Todd Broch97f259f2012-04-03 15:52:14 -0700294 ft2232_type = GOOGLE_SERVO_V2_PID1;
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +1100295 channel_count = 2;
Nicolas Boichatd520d3b2020-05-18 08:26:20 +0800296 msg_pwarn("Warning: Use 'google-servo-v2' instead!\n");
Nikolai Artemiev985f1952020-01-20 16:33:30 +1100297 /* Default divisor is too fast, and chip ID fails */
298 divisor = 6;
Todd Broch97f259f2012-04-03 15:52:14 -0700299 } else if (!strcasecmp(arg, "servo-v2-legacy")) {
300 ft2232_vid = GOOGLE_VID;
301 ft2232_type = GOOGLE_SERVO_V2_PID0;
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +1100302 channel_count = 2;
Nicolas Boichatd520d3b2020-05-18 08:26:20 +0800303 msg_pwarn("Warning: Use 'google-servo-v2-legacy' instead!\n");
Edward O'Callaghanb9a1dcf2020-03-02 17:14:14 +1100304 /* ^^ WARNING: deprecated ^^ */
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +1100305 } else if (!strcasecmp(arg, "flyswatter")) {
306 ft2232_type = FTDI_FT2232H_PID;
307 channel_count = 2;
308 /* Flyswatter and Flyswatter-2 require GPIO bits 0x80
309 * and 0x40 to be driven low to enable output buffers */
310 pindir = 0xcb;
hailfingerce670612010-11-10 03:26:57 +0000311 } else {
hailfinger1ef766d2010-07-06 09:55:48 +0000312 msg_perr("Error: Invalid device type specified.\n");
313 free(arg);
uwe56199592011-07-21 09:18:18 +0000314 return -1;
hailfinger1ef766d2010-07-06 09:55:48 +0000315 }
316 }
317 free(arg);
Edward O'Callaghan2068b922019-08-21 16:43:26 +1000318
hailfingerddeb4ac2010-07-08 10:13:37 +0000319 arg = extract_programmer_param("port");
hailfinger1ef766d2010-07-06 09:55:48 +0000320 if (arg) {
hailfingerebad21f2010-10-08 12:40:09 +0000321 switch (toupper((unsigned char)*arg)) {
hailfinger1ef766d2010-07-06 09:55:48 +0000322 case 'A':
323 ft2232_interface = INTERFACE_A;
324 break;
325 case 'B':
326 ft2232_interface = INTERFACE_B;
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +1100327 if (channel_count < 2)
328 channel_count = -1;
329 break;
330 case 'C':
331 ft2232_interface = INTERFACE_C;
332 if (channel_count < 3)
333 channel_count = -1;
334 break;
335 case 'D':
336 ft2232_interface = INTERFACE_D;
337 if (channel_count < 4)
338 channel_count = -1;
hailfinger1ef766d2010-07-06 09:55:48 +0000339 break;
340 default:
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +1100341 channel_count = -1;
342 break;
343 }
344 if (channel_count < 0 || strlen(arg) != 1) {
345 msg_perr("Error: Invalid channel/port/interface specified: \"%s\".\n", arg);
hailfinger1ef766d2010-07-06 09:55:48 +0000346 free(arg);
uwe56199592011-07-21 09:18:18 +0000347 return -2;
hailfinger1ef766d2010-07-06 09:55:48 +0000348 }
349 }
350 free(arg);
Nikolai Artemiev249cbab2020-02-07 11:53:15 +1100351
Nikolai Artemiev249cbab2020-02-07 11:53:15 +1100352 arg = extract_programmer_param("divisor");
353 if (arg && strlen(arg)) {
354 unsigned int temp = 0;
355 char *endptr;
356 temp = strtoul(arg, &endptr, 10);
357 if (*endptr || temp < 2 || temp > 131072 || temp & 0x1) {
358 msg_perr("Error: Invalid SPI frequency divisor specified: \"%s\".\n"
359 "Valid are even values between 2 and 131072.\n", arg);
360 free(arg);
361 return -2;
362 }
363 divisor = (uint32_t)temp;
364 }
365 free(arg);
366
sibradzic419c86f2020-02-04 18:24:58 +0900367 /* Allows setting multiple GPIOL states, for example: csgpiol=012 */
Sergey Alirzaev018a6df2018-08-01 16:39:17 +0300368 arg = extract_programmer_param("csgpiol");
369 if (arg) {
sibradzic419c86f2020-02-04 18:24:58 +0900370 unsigned int ngpios = strlen(arg);
371 for (unsigned int i = 0; i <= ngpios; i++) {
372 int temp = arg[i] - '0';
373 if (ngpios == 0 || (ngpios != i && (temp < 0 || temp > 3))) {
374 msg_perr("Error: Invalid GPIOLs specified: \"%s\".\n"
375 "Valid values are numbers between 0 and 3. "
376 "Multiple GPIOLs can be specified.\n", arg);
377 free(arg);
378 return -2;
379 } else {
380 unsigned int pin = temp + 4;
381 cs_bits |= 1 << pin;
382 pindir |= 1 << pin;
383 }
Sergey Alirzaev018a6df2018-08-01 16:39:17 +0300384 }
385 }
386 free(arg);
387
hailfinger888410e2010-07-29 15:54:53 +0000388 msg_pdbg("Using device type %s %s ",
uwe3dae6872010-07-29 19:57:55 +0000389 get_ft2232_vendorname(ft2232_vid, ft2232_type),
390 get_ft2232_devicename(ft2232_vid, ft2232_type));
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +1100391 msg_pdbg("channel %s.\n",
392 (ft2232_interface == INTERFACE_A) ? "A" :
393 (ft2232_interface == INTERFACE_B) ? "B" :
394 (ft2232_interface == INTERFACE_C) ? "C" : "D");
hailfingerf31da3d2009-06-16 21:08:06 +0000395
396 if (ftdi_init(ftdic) < 0) {
Edward O'Callaghan2068b922019-08-21 16:43:26 +1000397 msg_perr("ftdi_init failed.\n");
uwe56199592011-07-21 09:18:18 +0000398 return -3;
hailfingerf31da3d2009-06-16 21:08:06 +0000399 }
400
Todd Brochcbaba9c2014-09-22 12:11:03 -0700401 if (ftdi_set_interface(ftdic, ft2232_interface) < 0) {
Edward O'Callaghan2068b922019-08-21 16:43:26 +1000402 msg_perr("Unable to select channel (%s).\n", ftdi_get_error_string(ftdic));
Todd Brochcbaba9c2014-09-22 12:11:03 -0700403 }
404
Shik Chen5eb56242012-08-07 15:09:37 +0800405 arg = extract_programmer_param("serial");
406 f = ftdi_usb_open_desc(ftdic, ft2232_vid, ft2232_type, NULL, arg);
407 free(arg);
hailfingerf31da3d2009-06-16 21:08:06 +0000408
409 if (f < 0 && f != -5) {
snelson93932992010-01-10 01:08:37 +0000410 msg_perr("Unable to open FTDI device: %d (%s)\n", f,
hailfingerf31da3d2009-06-16 21:08:06 +0000411 ftdi_get_error_string(ftdic));
uwe56199592011-07-21 09:18:18 +0000412 return -4;
hailfingerf31da3d2009-06-16 21:08:06 +0000413 }
414
Nikolai Artemiev0a3fb592020-01-09 11:37:46 +1100415 if (ftdic->type != TYPE_2232H && ftdic->type != TYPE_4232H && ftdic->type != TYPE_232H) {
416 msg_pdbg("FTDI chip type %d is not high-speed.\n", ftdic->type);
hailfinger81f90f22010-11-10 03:18:41 +0000417 clock_5x = 0;
418 }
419
hailfingerb91c08c2011-08-15 19:54:20 +0000420 if (ftdi_usb_reset(ftdic) < 0) {
Edward O'Callaghan2068b922019-08-21 16:43:26 +1000421 msg_perr("Unable to reset FTDI device (%s).\n", ftdi_get_error_string(ftdic));
hailfingerb91c08c2011-08-15 19:54:20 +0000422 }
hailfingerf31da3d2009-06-16 21:08:06 +0000423
hailfingerb91c08c2011-08-15 19:54:20 +0000424 if (ftdi_set_latency_timer(ftdic, 2) < 0) {
Edward O'Callaghan2068b922019-08-21 16:43:26 +1000425 msg_perr("Unable to set latency timer (%s).\n", ftdi_get_error_string(ftdic));
hailfingerb91c08c2011-08-15 19:54:20 +0000426 }
hailfingerf31da3d2009-06-16 21:08:06 +0000427
el-coderon4fad4882020-03-20 18:52:15 +0100428 if (ftdi_write_data_set_chunksize(ftdic, 270)) {
Edward O'Callaghan2068b922019-08-21 16:43:26 +1000429 msg_perr("Unable to set chunk size (%s).\n", ftdi_get_error_string(ftdic));
hailfingerb91c08c2011-08-15 19:54:20 +0000430 }
hailfingerf31da3d2009-06-16 21:08:06 +0000431
hailfingerb91c08c2011-08-15 19:54:20 +0000432 if (ftdi_set_bitmode(ftdic, 0x00, BITMODE_BITBANG_SPI) < 0) {
Edward O'Callaghan2068b922019-08-21 16:43:26 +1000433 msg_perr("Unable to set bitmode to SPI (%s).\n", ftdi_get_error_string(ftdic));
hailfingerb91c08c2011-08-15 19:54:20 +0000434 }
hailfingerf31da3d2009-06-16 21:08:06 +0000435
hailfinger81f90f22010-11-10 03:18:41 +0000436 if (clock_5x) {
437 msg_pdbg("Disable divide-by-5 front stage\n");
Nikolai Artemieva5c9cd72020-01-08 10:40:19 +1100438 buf[0] = DIS_DIV_5;
uwe56199592011-07-21 09:18:18 +0000439 if (send_buf(ftdic, buf, 1)) {
440 ret = -5;
441 goto ftdi_err;
442 }
hailfinger81f90f22010-11-10 03:18:41 +0000443 mpsse_clk = 60.0;
444 } else {
445 mpsse_clk = 12.0;
Todd Broch77746652012-04-19 09:52:49 -0700446 }
Nikolai Artemiev985f1952020-01-20 16:33:30 +1100447
snelson93932992010-01-10 01:08:37 +0000448 msg_pdbg("Set clock divisor\n");
Nikolai Artemieva5c9cd72020-01-08 10:40:19 +1100449 buf[0] = TCK_DIVISOR;
Nikolai Artemiev985f1952020-01-20 16:33:30 +1100450 buf[1] = (divisor / 2 - 1) & 0xff;
451 buf[2] = ((divisor / 2 - 1) >> 8) & 0xff;
uwe56199592011-07-21 09:18:18 +0000452 if (send_buf(ftdic, buf, 3)) {
453 ret = -6;
454 goto ftdi_err;
455 }
hailfingerf31da3d2009-06-16 21:08:06 +0000456
Nikolai Artemiev985f1952020-01-20 16:33:30 +1100457 msg_pdbg("MPSSE clock: %f MHz, divisor: %u, SPI clock: %f MHz\n",
458 mpsse_clk, divisor, (double)(mpsse_clk / divisor));
hailfingerf31da3d2009-06-16 21:08:06 +0000459
uweb34ec9f2009-10-01 18:40:02 +0000460 /* Disconnect TDI/DO to TDO/DI for loopback. */
snelson93932992010-01-10 01:08:37 +0000461 msg_pdbg("No loopback of TDI/DO TDO/DI\n");
Nikolai Artemieva5c9cd72020-01-08 10:40:19 +1100462 buf[0] = LOOPBACK_END;
uwe56199592011-07-21 09:18:18 +0000463 if (send_buf(ftdic, buf, 1)) {
464 ret = -7;
465 goto ftdi_err;
466 }
hailfingerf31da3d2009-06-16 21:08:06 +0000467
snelson93932992010-01-10 01:08:37 +0000468 msg_pdbg("Set data bits\n");
hailfingerf31da3d2009-06-16 21:08:06 +0000469 buf[0] = SET_BITS_LOW;
hailfinger888410e2010-07-29 15:54:53 +0000470 buf[1] = cs_bits;
471 buf[2] = pindir;
uwe56199592011-07-21 09:18:18 +0000472 if (send_buf(ftdic, buf, 3)) {
473 ret = -8;
474 goto ftdi_err;
475 }
hailfingerf31da3d2009-06-16 21:08:06 +0000476
Patrick Georgif4f1e2f2017-03-10 17:38:40 +0100477 register_spi_master(&spi_master_ft2232);
hailfingerf31da3d2009-06-16 21:08:06 +0000478
479 return 0;
uwe56199592011-07-21 09:18:18 +0000480
481ftdi_err:
482 if ((f = ftdi_usb_close(ftdic)) < 0) {
483 msg_perr("Unable to close FTDI device: %d (%s)\n", f,
484 ftdi_get_error_string(ftdic));
485 }
uwe56199592011-07-21 09:18:18 +0000486 return ret;
hailfingerf31da3d2009-06-16 21:08:06 +0000487}
488
uwe56199592011-07-21 09:18:18 +0000489/* Returns 0 upon success, a negative number upon errors. */
Nikolai Artemiev0a635262020-02-11 13:49:52 +1100490static int ft2232_spi_send_command(const struct flashctx *flash,
491 unsigned int writecnt, unsigned int readcnt,
492 const unsigned char *writearr,
493 unsigned char *readarr)
hailfingerf31da3d2009-06-16 21:08:06 +0000494{
495 struct ftdi_context *ftdic = &ftdic_context;
496 static unsigned char *buf = NULL;
hailfinger322be712009-11-22 01:33:40 +0000497 /* failed is special. We use bitwise ops, but it is essentially bool. */
hailfingerb91c08c2011-08-15 19:54:20 +0000498 int i = 0, ret = 0, failed = 0;
Angel Pons546ca742020-03-31 15:34:35 +0200499 size_t bufsize;
500 static size_t oldbufsize = 0;
hailfingerf31da3d2009-06-16 21:08:06 +0000501
hailfinger9c290a72009-07-14 10:26:56 +0000502 if (writecnt > 65536 || readcnt > 65536)
503 return SPI_INVALID_LENGTH;
504
hailfinger90604662009-11-25 16:58:17 +0000505 /* buf is not used for the response from the chip. */
506 bufsize = max(writecnt + 9, 260 + 9);
507 /* Never shrink. realloc() calls are expensive. */
Angel Pons546ca742020-03-31 15:34:35 +0200508 if (!buf || bufsize > oldbufsize) {
hailfinger90604662009-11-25 16:58:17 +0000509 buf = realloc(buf, bufsize);
510 if (!buf) {
snelson93932992010-01-10 01:08:37 +0000511 msg_perr("Out of memory!\n");
uwe56199592011-07-21 09:18:18 +0000512 /* TODO: What to do with buf? */
513 return SPI_GENERIC_ERROR;
hailfinger90604662009-11-25 16:58:17 +0000514 }
515 oldbufsize = bufsize;
hailfingerf31da3d2009-06-16 21:08:06 +0000516 }
517
uweb34ec9f2009-10-01 18:40:02 +0000518 /*
519 * Minimize USB transfers by packing as many commands as possible
520 * together. If we're not expecting to read, we can assert CS#, write,
521 * and deassert CS# all in one shot. If reading, we do three separate
stepana5807bf2009-09-16 08:26:59 +0000522 * operations.
523 */
snelson93932992010-01-10 01:08:37 +0000524 msg_pspew("Assert CS#\n");
hailfingerf31da3d2009-06-16 21:08:06 +0000525 buf[i++] = SET_BITS_LOW;
sibradzic9ee0f202020-02-14 17:15:02 +0900526 buf[i++] = ~ 0x08 & cs_bits; /* assert CS (3rd) bit only */
hailfinger888410e2010-07-29 15:54:53 +0000527 buf[i++] = pindir;
hailfingerf31da3d2009-06-16 21:08:06 +0000528
529 if (writecnt) {
Nikolai Artemieva5c9cd72020-01-08 10:40:19 +1100530 buf[i++] = MPSSE_DO_WRITE | MPSSE_WRITE_NEG;
hailfingerf31da3d2009-06-16 21:08:06 +0000531 buf[i++] = (writecnt - 1) & 0xff;
532 buf[i++] = ((writecnt - 1) >> 8) & 0xff;
uweb34ec9f2009-10-01 18:40:02 +0000533 memcpy(buf + i, writearr, writecnt);
hailfingerf31da3d2009-06-16 21:08:06 +0000534 i += writecnt;
535 }
536
uweb34ec9f2009-10-01 18:40:02 +0000537 /*
538 * Optionally terminate this batch of commands with a
hailfingerf31da3d2009-06-16 21:08:06 +0000539 * read command, then do the fetch of the results.
540 */
541 if (readcnt) {
Nikolai Artemieva5c9cd72020-01-08 10:40:19 +1100542 buf[i++] = MPSSE_DO_READ;
hailfingerf31da3d2009-06-16 21:08:06 +0000543 buf[i++] = (readcnt - 1) & 0xff;
544 buf[i++] = ((readcnt - 1) >> 8) & 0xff;
545 ret = send_buf(ftdic, buf, i);
hailfinger322be712009-11-22 01:33:40 +0000546 failed = ret;
547 /* We can't abort here, we still have to deassert CS#. */
548 if (ret)
uwe8d342eb2011-07-28 08:13:25 +0000549 msg_perr("send_buf failed before read: %i\n", ret);
hailfingerf31da3d2009-06-16 21:08:06 +0000550 i = 0;
stepana5807bf2009-09-16 08:26:59 +0000551 if (ret == 0) {
uweb34ec9f2009-10-01 18:40:02 +0000552 /*
553 * FIXME: This is unreliable. There's no guarantee that
554 * we read the response directly after sending the read
555 * command. We may be scheduled out etc.
stepana5807bf2009-09-16 08:26:59 +0000556 */
557 ret = get_buf(ftdic, readarr, readcnt);
hailfinger322be712009-11-22 01:33:40 +0000558 failed |= ret;
559 /* We can't abort here either. */
560 if (ret)
snelson93932992010-01-10 01:08:37 +0000561 msg_perr("get_buf failed: %i\n", ret);
stepana5807bf2009-09-16 08:26:59 +0000562 }
hailfingerf31da3d2009-06-16 21:08:06 +0000563 }
564
snelson93932992010-01-10 01:08:37 +0000565 msg_pspew("De-assert CS#\n");
hailfingerf31da3d2009-06-16 21:08:06 +0000566 buf[i++] = SET_BITS_LOW;
hailfinger888410e2010-07-29 15:54:53 +0000567 buf[i++] = cs_bits;
568 buf[i++] = pindir;
hailfinger322be712009-11-22 01:33:40 +0000569 ret = send_buf(ftdic, buf, i);
570 failed |= ret;
571 if (ret)
snelson93932992010-01-10 01:08:37 +0000572 msg_perr("send_buf failed at end: %i\n", ret);
hailfingerf31da3d2009-06-16 21:08:06 +0000573
hailfinger322be712009-11-22 01:33:40 +0000574 return failed ? -1 : 0;
hailfingerf31da3d2009-06-16 21:08:06 +0000575}
576
hailfingerf31da3d2009-06-16 21:08:06 +0000577#endif