1*0d6140beSAndroid Build Coastguard Worker /*
2*0d6140beSAndroid Build Coastguard Worker * This file is part of the flashrom project.
3*0d6140beSAndroid Build Coastguard Worker *
4*0d6140beSAndroid Build Coastguard Worker * Copyright (C) 2012 James Laird <[email protected]>
5*0d6140beSAndroid Build Coastguard Worker *
6*0d6140beSAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or modify
7*0d6140beSAndroid Build Coastguard Worker * it under the terms of the GNU General Public License as published by
8*0d6140beSAndroid Build Coastguard Worker * the Free Software Foundation; version 2 of the License.
9*0d6140beSAndroid Build Coastguard Worker *
10*0d6140beSAndroid Build Coastguard Worker * This program is distributed in the hope that it will be useful,
11*0d6140beSAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*0d6140beSAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*0d6140beSAndroid Build Coastguard Worker * GNU General Public License for more details.
14*0d6140beSAndroid Build Coastguard Worker */
15*0d6140beSAndroid Build Coastguard Worker
16*0d6140beSAndroid Build Coastguard Worker /*
17*0d6140beSAndroid Build Coastguard Worker * Device should be connected as per "active serial" mode:
18*0d6140beSAndroid Build Coastguard Worker *
19*0d6140beSAndroid Build Coastguard Worker * +---------+------+-----------+
20*0d6140beSAndroid Build Coastguard Worker * | SPI | Pin | Altera |
21*0d6140beSAndroid Build Coastguard Worker * +---------+------+-----------+
22*0d6140beSAndroid Build Coastguard Worker * | SCLK | 1 | DCLK |
23*0d6140beSAndroid Build Coastguard Worker * | GND | 2,10 | GND |
24*0d6140beSAndroid Build Coastguard Worker * | VCC | 4 | VCC(TRGT) |
25*0d6140beSAndroid Build Coastguard Worker * | MISO | 7 | DATAOUT |
26*0d6140beSAndroid Build Coastguard Worker * | /CS | 8 | nCS |
27*0d6140beSAndroid Build Coastguard Worker * | MOSI | 9 | ASDI |
28*0d6140beSAndroid Build Coastguard Worker * +---------+------+-----------+
29*0d6140beSAndroid Build Coastguard Worker *
30*0d6140beSAndroid Build Coastguard Worker * See also the USB-Blaster Download Cable User Guide: http://www.altera.com/literature/ug/ug_usb_blstr.pdf
31*0d6140beSAndroid Build Coastguard Worker */
32*0d6140beSAndroid Build Coastguard Worker
33*0d6140beSAndroid Build Coastguard Worker #include <stdio.h>
34*0d6140beSAndroid Build Coastguard Worker #include <string.h>
35*0d6140beSAndroid Build Coastguard Worker #include <stdlib.h>
36*0d6140beSAndroid Build Coastguard Worker #include <ctype.h>
37*0d6140beSAndroid Build Coastguard Worker #include <ftdi.h>
38*0d6140beSAndroid Build Coastguard Worker #include "flash.h"
39*0d6140beSAndroid Build Coastguard Worker #include "programmer.h"
40*0d6140beSAndroid Build Coastguard Worker #include "spi.h"
41*0d6140beSAndroid Build Coastguard Worker
42*0d6140beSAndroid Build Coastguard Worker /* Please keep sorted by vendor ID, then device ID. */
43*0d6140beSAndroid Build Coastguard Worker #define ALTERA_VID 0x09fb
44*0d6140beSAndroid Build Coastguard Worker #define ALTERA_USBBLASTER_PID 0x6001
45*0d6140beSAndroid Build Coastguard Worker
46*0d6140beSAndroid Build Coastguard Worker static const struct dev_entry devs_usbblasterspi[] = {
47*0d6140beSAndroid Build Coastguard Worker {ALTERA_VID, ALTERA_USBBLASTER_PID, OK, "Altera", "USB-Blaster"},
48*0d6140beSAndroid Build Coastguard Worker
49*0d6140beSAndroid Build Coastguard Worker {0}
50*0d6140beSAndroid Build Coastguard Worker };
51*0d6140beSAndroid Build Coastguard Worker
52*0d6140beSAndroid Build Coastguard Worker struct usbblaster_spi_data {
53*0d6140beSAndroid Build Coastguard Worker struct ftdi_context ftdic;
54*0d6140beSAndroid Build Coastguard Worker };
55*0d6140beSAndroid Build Coastguard Worker
56*0d6140beSAndroid Build Coastguard Worker // command bytes
57*0d6140beSAndroid Build Coastguard Worker #define BIT_BYTE (1<<7) // byte mode (rather than bitbang)
58*0d6140beSAndroid Build Coastguard Worker #define BIT_READ (1<<6) // read request
59*0d6140beSAndroid Build Coastguard Worker #define BIT_LED (1<<5)
60*0d6140beSAndroid Build Coastguard Worker #define BIT_CS (1<<3)
61*0d6140beSAndroid Build Coastguard Worker #define BIT_TMS (1<<1)
62*0d6140beSAndroid Build Coastguard Worker #define BIT_CLK (1<<0)
63*0d6140beSAndroid Build Coastguard Worker
64*0d6140beSAndroid Build Coastguard Worker #define BUF_SIZE 64
65*0d6140beSAndroid Build Coastguard Worker
66*0d6140beSAndroid Build Coastguard Worker /* The programmer shifts bits in the wrong order for SPI, so we use this method to reverse the bits when needed.
67*0d6140beSAndroid Build Coastguard Worker * http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits */
reverse(uint8_t b)68*0d6140beSAndroid Build Coastguard Worker static uint8_t reverse(uint8_t b)
69*0d6140beSAndroid Build Coastguard Worker {
70*0d6140beSAndroid Build Coastguard Worker return ((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
71*0d6140beSAndroid Build Coastguard Worker }
72*0d6140beSAndroid Build Coastguard Worker
send_write(unsigned int writecnt,const unsigned char * writearr,struct ftdi_context ftdic)73*0d6140beSAndroid Build Coastguard Worker static int send_write(unsigned int writecnt, const unsigned char *writearr, struct ftdi_context ftdic)
74*0d6140beSAndroid Build Coastguard Worker {
75*0d6140beSAndroid Build Coastguard Worker uint8_t buf[BUF_SIZE] = { 0 };
76*0d6140beSAndroid Build Coastguard Worker
77*0d6140beSAndroid Build Coastguard Worker while (writecnt) {
78*0d6140beSAndroid Build Coastguard Worker unsigned int i;
79*0d6140beSAndroid Build Coastguard Worker unsigned int n_write = min(writecnt, BUF_SIZE - 1);
80*0d6140beSAndroid Build Coastguard Worker msg_pspew("writing %d-byte packet\n", n_write);
81*0d6140beSAndroid Build Coastguard Worker
82*0d6140beSAndroid Build Coastguard Worker buf[0] = BIT_BYTE | (uint8_t)n_write;
83*0d6140beSAndroid Build Coastguard Worker for (i = 0; i < n_write; i++) {
84*0d6140beSAndroid Build Coastguard Worker buf[i+1] = reverse(writearr[i]);
85*0d6140beSAndroid Build Coastguard Worker }
86*0d6140beSAndroid Build Coastguard Worker if (ftdi_write_data(&ftdic, buf, n_write + 1) < 0) {
87*0d6140beSAndroid Build Coastguard Worker msg_perr("USB-Blaster write failed\n");
88*0d6140beSAndroid Build Coastguard Worker return -1;
89*0d6140beSAndroid Build Coastguard Worker }
90*0d6140beSAndroid Build Coastguard Worker
91*0d6140beSAndroid Build Coastguard Worker writearr += n_write;
92*0d6140beSAndroid Build Coastguard Worker writecnt -= n_write;
93*0d6140beSAndroid Build Coastguard Worker }
94*0d6140beSAndroid Build Coastguard Worker return 0;
95*0d6140beSAndroid Build Coastguard Worker }
96*0d6140beSAndroid Build Coastguard Worker
send_read(unsigned int readcnt,unsigned char * readarr,struct ftdi_context ftdic)97*0d6140beSAndroid Build Coastguard Worker static int send_read(unsigned int readcnt, unsigned char *readarr, struct ftdi_context ftdic)
98*0d6140beSAndroid Build Coastguard Worker {
99*0d6140beSAndroid Build Coastguard Worker int i;
100*0d6140beSAndroid Build Coastguard Worker unsigned int n_read;
101*0d6140beSAndroid Build Coastguard Worker uint8_t buf[BUF_SIZE] = { 0 };
102*0d6140beSAndroid Build Coastguard Worker
103*0d6140beSAndroid Build Coastguard Worker n_read = readcnt;
104*0d6140beSAndroid Build Coastguard Worker while (n_read) {
105*0d6140beSAndroid Build Coastguard Worker unsigned int payload_size = min(n_read, BUF_SIZE - 1);
106*0d6140beSAndroid Build Coastguard Worker msg_pspew("reading %d-byte packet\n", payload_size);
107*0d6140beSAndroid Build Coastguard Worker
108*0d6140beSAndroid Build Coastguard Worker buf[0] = BIT_BYTE | BIT_READ | (uint8_t)payload_size;
109*0d6140beSAndroid Build Coastguard Worker if (ftdi_write_data(&ftdic, buf, payload_size + 1) < 0) {
110*0d6140beSAndroid Build Coastguard Worker msg_perr("USB-Blaster write failed\n");
111*0d6140beSAndroid Build Coastguard Worker return -1;
112*0d6140beSAndroid Build Coastguard Worker }
113*0d6140beSAndroid Build Coastguard Worker n_read -= payload_size;
114*0d6140beSAndroid Build Coastguard Worker }
115*0d6140beSAndroid Build Coastguard Worker
116*0d6140beSAndroid Build Coastguard Worker n_read = readcnt;
117*0d6140beSAndroid Build Coastguard Worker while (n_read) {
118*0d6140beSAndroid Build Coastguard Worker int ret = ftdi_read_data(&ftdic, readarr, n_read);
119*0d6140beSAndroid Build Coastguard Worker if (ret < 0) {
120*0d6140beSAndroid Build Coastguard Worker msg_perr("USB-Blaster read failed\n");
121*0d6140beSAndroid Build Coastguard Worker return -1;
122*0d6140beSAndroid Build Coastguard Worker }
123*0d6140beSAndroid Build Coastguard Worker for (i = 0; i < ret; i++) {
124*0d6140beSAndroid Build Coastguard Worker readarr[i] = reverse(readarr[i]);
125*0d6140beSAndroid Build Coastguard Worker }
126*0d6140beSAndroid Build Coastguard Worker n_read -= ret;
127*0d6140beSAndroid Build Coastguard Worker readarr += ret;
128*0d6140beSAndroid Build Coastguard Worker }
129*0d6140beSAndroid Build Coastguard Worker return 0;
130*0d6140beSAndroid Build Coastguard Worker }
131*0d6140beSAndroid Build Coastguard Worker
132*0d6140beSAndroid Build Coastguard Worker /* Returns 0 upon success, a negative number upon errors. */
usbblaster_spi_send_command(const struct flashctx * flash,unsigned int writecnt,unsigned int readcnt,const unsigned char * writearr,unsigned char * readarr)133*0d6140beSAndroid Build Coastguard Worker static int usbblaster_spi_send_command(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
134*0d6140beSAndroid Build Coastguard Worker const unsigned char *writearr, unsigned char *readarr)
135*0d6140beSAndroid Build Coastguard Worker {
136*0d6140beSAndroid Build Coastguard Worker struct usbblaster_spi_data *usbblaster_data = flash->mst->spi.data;
137*0d6140beSAndroid Build Coastguard Worker uint8_t cmd;
138*0d6140beSAndroid Build Coastguard Worker int ret = 0;
139*0d6140beSAndroid Build Coastguard Worker
140*0d6140beSAndroid Build Coastguard Worker cmd = BIT_LED; // asserts /CS
141*0d6140beSAndroid Build Coastguard Worker if (ftdi_write_data(&usbblaster_data->ftdic, &cmd, 1) < 0) {
142*0d6140beSAndroid Build Coastguard Worker msg_perr("USB-Blaster enable chip select failed\n");
143*0d6140beSAndroid Build Coastguard Worker ret = -1;
144*0d6140beSAndroid Build Coastguard Worker }
145*0d6140beSAndroid Build Coastguard Worker
146*0d6140beSAndroid Build Coastguard Worker if (!ret && writecnt)
147*0d6140beSAndroid Build Coastguard Worker ret = send_write(writecnt, writearr, usbblaster_data->ftdic);
148*0d6140beSAndroid Build Coastguard Worker
149*0d6140beSAndroid Build Coastguard Worker if (!ret && readcnt)
150*0d6140beSAndroid Build Coastguard Worker ret = send_read(readcnt, readarr, usbblaster_data->ftdic);
151*0d6140beSAndroid Build Coastguard Worker
152*0d6140beSAndroid Build Coastguard Worker cmd = BIT_CS;
153*0d6140beSAndroid Build Coastguard Worker if (ftdi_write_data(&usbblaster_data->ftdic, &cmd, 1) < 0) {
154*0d6140beSAndroid Build Coastguard Worker msg_perr("USB-Blaster disable chip select failed\n");
155*0d6140beSAndroid Build Coastguard Worker ret = -1;
156*0d6140beSAndroid Build Coastguard Worker }
157*0d6140beSAndroid Build Coastguard Worker
158*0d6140beSAndroid Build Coastguard Worker return ret;
159*0d6140beSAndroid Build Coastguard Worker }
160*0d6140beSAndroid Build Coastguard Worker
usbblaster_shutdown(void * data)161*0d6140beSAndroid Build Coastguard Worker static int usbblaster_shutdown(void *data)
162*0d6140beSAndroid Build Coastguard Worker {
163*0d6140beSAndroid Build Coastguard Worker free(data);
164*0d6140beSAndroid Build Coastguard Worker return 0;
165*0d6140beSAndroid Build Coastguard Worker }
166*0d6140beSAndroid Build Coastguard Worker
167*0d6140beSAndroid Build Coastguard Worker static const struct spi_master spi_master_usbblaster = {
168*0d6140beSAndroid Build Coastguard Worker .max_data_read = 256,
169*0d6140beSAndroid Build Coastguard Worker .max_data_write = 256,
170*0d6140beSAndroid Build Coastguard Worker .command = usbblaster_spi_send_command,
171*0d6140beSAndroid Build Coastguard Worker .read = default_spi_read,
172*0d6140beSAndroid Build Coastguard Worker .write_256 = default_spi_write_256,
173*0d6140beSAndroid Build Coastguard Worker .shutdown = usbblaster_shutdown,
174*0d6140beSAndroid Build Coastguard Worker };
175*0d6140beSAndroid Build Coastguard Worker
176*0d6140beSAndroid Build Coastguard Worker /* Returns 0 upon success, a negative number upon errors. */
usbblaster_spi_init(const struct programmer_cfg * cfg)177*0d6140beSAndroid Build Coastguard Worker static int usbblaster_spi_init(const struct programmer_cfg *cfg)
178*0d6140beSAndroid Build Coastguard Worker {
179*0d6140beSAndroid Build Coastguard Worker uint8_t buf[BUF_SIZE + 1] = { 0 };
180*0d6140beSAndroid Build Coastguard Worker struct ftdi_context ftdic;
181*0d6140beSAndroid Build Coastguard Worker struct usbblaster_spi_data *usbblaster_data;
182*0d6140beSAndroid Build Coastguard Worker
183*0d6140beSAndroid Build Coastguard Worker if (ftdi_init(&ftdic) < 0)
184*0d6140beSAndroid Build Coastguard Worker return -1;
185*0d6140beSAndroid Build Coastguard Worker
186*0d6140beSAndroid Build Coastguard Worker if (ftdi_usb_open(&ftdic, ALTERA_VID, ALTERA_USBBLASTER_PID) < 0) {
187*0d6140beSAndroid Build Coastguard Worker msg_perr("Failed to open USB-Blaster: %s\n", ftdic.error_str);
188*0d6140beSAndroid Build Coastguard Worker return -1;
189*0d6140beSAndroid Build Coastguard Worker }
190*0d6140beSAndroid Build Coastguard Worker
191*0d6140beSAndroid Build Coastguard Worker if (ftdi_usb_reset(&ftdic) < 0) {
192*0d6140beSAndroid Build Coastguard Worker msg_perr("USB-Blaster reset failed\n");
193*0d6140beSAndroid Build Coastguard Worker return -1;
194*0d6140beSAndroid Build Coastguard Worker }
195*0d6140beSAndroid Build Coastguard Worker
196*0d6140beSAndroid Build Coastguard Worker if (ftdi_set_latency_timer(&ftdic, 2) < 0) {
197*0d6140beSAndroid Build Coastguard Worker msg_perr("USB-Blaster set latency timer failed\n");
198*0d6140beSAndroid Build Coastguard Worker return -1;
199*0d6140beSAndroid Build Coastguard Worker }
200*0d6140beSAndroid Build Coastguard Worker
201*0d6140beSAndroid Build Coastguard Worker if (ftdi_write_data_set_chunksize(&ftdic, 4096) < 0 ||
202*0d6140beSAndroid Build Coastguard Worker ftdi_read_data_set_chunksize(&ftdic, BUF_SIZE) < 0) {
203*0d6140beSAndroid Build Coastguard Worker msg_perr("USB-Blaster set chunk size failed\n");
204*0d6140beSAndroid Build Coastguard Worker return -1;
205*0d6140beSAndroid Build Coastguard Worker }
206*0d6140beSAndroid Build Coastguard Worker
207*0d6140beSAndroid Build Coastguard Worker buf[sizeof(buf)-1] = BIT_LED | BIT_CS;
208*0d6140beSAndroid Build Coastguard Worker if (ftdi_write_data(&ftdic, buf, sizeof(buf)) < 0) {
209*0d6140beSAndroid Build Coastguard Worker msg_perr("USB-Blaster reset write failed\n");
210*0d6140beSAndroid Build Coastguard Worker return -1;
211*0d6140beSAndroid Build Coastguard Worker }
212*0d6140beSAndroid Build Coastguard Worker if (ftdi_read_data(&ftdic, buf, sizeof(buf)) < 0) {
213*0d6140beSAndroid Build Coastguard Worker msg_perr("USB-Blaster reset read failed\n");
214*0d6140beSAndroid Build Coastguard Worker return -1;
215*0d6140beSAndroid Build Coastguard Worker }
216*0d6140beSAndroid Build Coastguard Worker
217*0d6140beSAndroid Build Coastguard Worker usbblaster_data = calloc(1, sizeof(*usbblaster_data));
218*0d6140beSAndroid Build Coastguard Worker if (!usbblaster_data) {
219*0d6140beSAndroid Build Coastguard Worker msg_perr("Unable to allocate space for SPI master data\n");
220*0d6140beSAndroid Build Coastguard Worker return -1;
221*0d6140beSAndroid Build Coastguard Worker }
222*0d6140beSAndroid Build Coastguard Worker usbblaster_data->ftdic = ftdic;
223*0d6140beSAndroid Build Coastguard Worker
224*0d6140beSAndroid Build Coastguard Worker return register_spi_master(&spi_master_usbblaster, usbblaster_data);
225*0d6140beSAndroid Build Coastguard Worker }
226*0d6140beSAndroid Build Coastguard Worker
227*0d6140beSAndroid Build Coastguard Worker const struct programmer_entry programmer_usbblaster_spi = {
228*0d6140beSAndroid Build Coastguard Worker .name = "usbblaster_spi",
229*0d6140beSAndroid Build Coastguard Worker .type = USB,
230*0d6140beSAndroid Build Coastguard Worker .devs.dev = devs_usbblasterspi,
231*0d6140beSAndroid Build Coastguard Worker .init = usbblaster_spi_init,
232*0d6140beSAndroid Build Coastguard Worker };
233