1 /*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2010 Carl-Daniel Hailfinger
5 * Copyright (C) 2014 Justin Chevrier
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
17 /*
18 * Connections are as follows:
19 *
20 * +------+-----+----------+
21 * | SPI | Pin | PICkit2 |
22 * +------+-----+----------+
23 * | /CS | 1 | VPP/MCLR |
24 * | VCC | 2 | VDD |
25 * | GND | 3 | GND |
26 * | MISO | 4 | PGD |
27 * | SCLK | 5 | PDC |
28 * | MOSI | 6 | AUX |
29 * +------+-----+----------+
30 *
31 * Inspiration and some specifics of the interface came via the AVRDude
32 * PICkit2 code: https://github.com/steve-m/avrdude/blob/master/pickit2.c
33 */
34
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <limits.h>
39 #include <errno.h>
40 #include <libusb.h>
41
42 #include "flash.h"
43 #include "chipdrivers.h"
44 #include "programmer.h"
45 #include "spi.h"
46
47 static const struct dev_entry devs_pickit2_spi[] = {
48 {0x04D8, 0x0033, OK, "Microchip", "PICkit 2"},
49
50 {0}
51 };
52
53 struct pickit2_spi_data {
54 libusb_device_handle *pickit2_handle;
55 };
56
57 /* Default USB transaction timeout in ms */
58 #define DFLT_TIMEOUT 10000
59
60 #define CMD_LENGTH 64
61 #define ENDPOINT_OUT 0x01
62 #define ENDPOINT_IN 0x81
63
64 #define CMD_GET_VERSION 0x76
65 #define CMD_SET_VDD 0xA0
66 #define CMD_SET_VPP 0xA1
67 #define CMD_READ_VDD_VPP 0xA3
68 #define CMD_EXEC_SCRIPT 0xA6
69 #define CMD_CLR_DLOAD_BUFF 0xA7
70 #define CMD_DOWNLOAD_DATA 0xA8
71 #define CMD_CLR_ULOAD_BUFF 0xA9
72 #define CMD_UPLOAD_DATA 0xAA
73 #define CMD_END_OF_BUFFER 0xAD
74
75 #define SCR_SPI_READ_BUF 0xC5
76 #define SCR_SPI_WRITE_BUF 0xC6
77 #define SCR_SET_AUX 0xCF
78 #define SCR_LOOP 0xE9
79 #define SCR_SET_ICSP_CLK_PERIOD 0xEA
80 #define SCR_SET_PINS 0xF3
81 #define SCR_BUSY_LED_OFF 0xF4
82 #define SCR_BUSY_LED_ON 0xF5
83 #define SCR_MCLR_GND_OFF 0xF6
84 #define SCR_MCLR_GND_ON 0xF7
85 #define SCR_VPP_PWM_OFF 0xF8
86 #define SCR_VPP_PWM_ON 0xF9
87 #define SCR_VPP_OFF 0xFA
88 #define SCR_VPP_ON 0xFB
89 #define SCR_VDD_OFF 0xFE
90 #define SCR_VDD_ON 0xFF
91
pickit2_interrupt_transfer(libusb_device_handle * handle,unsigned char endpoint,unsigned char * data)92 static int pickit2_interrupt_transfer(libusb_device_handle *handle, unsigned char endpoint, unsigned char *data)
93 {
94 int transferred;
95 return libusb_interrupt_transfer(handle, endpoint, data, CMD_LENGTH, &transferred, DFLT_TIMEOUT);
96 }
97
pickit2_get_firmware_version(libusb_device_handle * pickit2_handle)98 static int pickit2_get_firmware_version(libusb_device_handle *pickit2_handle)
99 {
100 int ret;
101 uint8_t command[CMD_LENGTH] = {CMD_GET_VERSION, CMD_END_OF_BUFFER};
102
103 ret = pickit2_interrupt_transfer(pickit2_handle, ENDPOINT_OUT, command);
104
105 if (ret != 0) {
106 msg_perr("Command Get Firmware Version failed!\n");
107 return 1;
108 }
109
110 ret = pickit2_interrupt_transfer(pickit2_handle, ENDPOINT_IN, command);
111
112 if (ret != 0) {
113 msg_perr("Command Get Firmware Version failed!\n");
114 return 1;
115 }
116
117 msg_pdbg("PICkit2 Firmware Version: %d.%d\n", (int)command[0], (int)command[1]);
118 return 0;
119 }
120
pickit2_set_spi_voltage(libusb_device_handle * pickit2_handle,int millivolt)121 static int pickit2_set_spi_voltage(libusb_device_handle *pickit2_handle, int millivolt)
122 {
123 double voltage_selector;
124 switch (millivolt) {
125 case 0:
126 /* Admittedly this one is an assumption. */
127 voltage_selector = 0;
128 break;
129 case 1800:
130 voltage_selector = 1.8;
131 break;
132 case 2500:
133 voltage_selector = 2.5;
134 break;
135 case 3500:
136 voltage_selector = 3.5;
137 break;
138 default:
139 msg_perr("Unknown voltage %i mV! Aborting.\n", millivolt);
140 return 1;
141 }
142 msg_pdbg("Setting SPI voltage to %u.%03u V\n", millivolt / 1000,
143 millivolt % 1000);
144
145 uint8_t command[CMD_LENGTH] = {
146 CMD_SET_VDD,
147 voltage_selector * 2048 + 672,
148 (voltage_selector * 2048 + 672) / 256,
149 voltage_selector * 36,
150 CMD_SET_VPP,
151 0x40,
152 voltage_selector * 18.61,
153 voltage_selector * 13,
154 CMD_END_OF_BUFFER
155 };
156 int ret = pickit2_interrupt_transfer(pickit2_handle, ENDPOINT_OUT, command);
157
158 if (ret != 0) {
159 msg_perr("Command Set Voltage failed!\n");
160 return 1;
161 }
162
163 return 0;
164 }
165
166 struct pickit2_spispeeds {
167 const char *const name;
168 const int speed;
169 };
170
171 static const struct pickit2_spispeeds spispeeds[] = {
172 { "1M", 0x1 },
173 { "500k", 0x2 },
174 { "333k", 0x3 },
175 { "250k", 0x4 },
176 { NULL, 0x0 },
177 };
178
pickit2_set_spi_speed(libusb_device_handle * pickit2_handle,unsigned int spispeed_idx)179 static int pickit2_set_spi_speed(libusb_device_handle *pickit2_handle, unsigned int spispeed_idx)
180 {
181 msg_pdbg("SPI speed is %sHz\n", spispeeds[spispeed_idx].name);
182
183 uint8_t command[CMD_LENGTH] = {
184 CMD_EXEC_SCRIPT,
185 2,
186 SCR_SET_ICSP_CLK_PERIOD,
187 spispeed_idx,
188 CMD_END_OF_BUFFER
189 };
190
191 int ret = pickit2_interrupt_transfer(pickit2_handle, ENDPOINT_OUT, command);
192
193 if (ret != 0) {
194 msg_perr("Command Set SPI Speed failed!\n");
195 return 1;
196 }
197
198 return 0;
199 }
200
pickit2_spi_send_command(const struct flashctx * flash,unsigned int writecnt,unsigned int readcnt,const unsigned char * writearr,unsigned char * readarr)201 static int pickit2_spi_send_command(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
202 const unsigned char *writearr, unsigned char *readarr)
203 {
204 struct pickit2_spi_data *pickit2_data = flash->mst->spi.data;
205 const unsigned int total_packetsize = writecnt + readcnt + 20;
206
207 /* Maximum number of bytes per transaction (including command overhead) is 64. Lets play it safe
208 * and always assume the worst case scenario of 20 bytes command overhead.
209 */
210 if (total_packetsize > CMD_LENGTH) {
211 msg_perr("\nTotal packetsize (%i) is greater than %i supported, aborting.\n",
212 total_packetsize, CMD_LENGTH);
213 return 1;
214 }
215
216 uint8_t buf[CMD_LENGTH] = {CMD_DOWNLOAD_DATA, writecnt};
217 unsigned int i = 2;
218 for (; i < writecnt + 2; i++) {
219 buf[i] = writearr[i - 2];
220 }
221
222 buf[i++] = CMD_CLR_ULOAD_BUFF;
223 buf[i++] = CMD_EXEC_SCRIPT;
224
225 /* Determine script length based on number of bytes to be read or written */
226 if (writecnt == 1 && readcnt == 1)
227 buf[i++] = 7;
228 else if (writecnt == 1 || readcnt == 1)
229 buf[i++] = 10;
230 else
231 buf[i++] = 13;
232
233 /* Assert CS# */
234 buf[i++] = SCR_VPP_OFF;
235 buf[i++] = SCR_MCLR_GND_ON;
236
237 buf[i++] = SCR_SPI_WRITE_BUF;
238
239 if (writecnt > 1) {
240 buf[i++] = SCR_LOOP;
241 buf[i++] = 1; /* Loop back one instruction */
242 buf[i++] = writecnt - 1; /* Number of times to loop */
243 }
244
245 if (readcnt)
246 buf[i++] = SCR_SPI_READ_BUF;
247
248 if (readcnt > 1) {
249 buf[i++] = SCR_LOOP;
250 buf[i++] = 1; /* Loop back one instruction */
251 buf[i++] = readcnt - 1; /* Number of times to loop */
252 }
253
254 /* De-assert CS# */
255 buf[i++] = SCR_MCLR_GND_OFF;
256 buf[i++] = SCR_VPP_PWM_ON;
257 buf[i++] = SCR_VPP_ON;
258
259 buf[i++] = CMD_UPLOAD_DATA;
260 buf[i++] = CMD_END_OF_BUFFER;
261
262 int ret = pickit2_interrupt_transfer(pickit2_data->pickit2_handle, ENDPOINT_OUT, buf);
263
264 if (ret != 0) {
265 msg_perr("Send SPI failed!\n");
266 return 1;
267 }
268
269 if (readcnt) {
270 int length = 0;
271 ret = libusb_interrupt_transfer(pickit2_data->pickit2_handle,
272 ENDPOINT_IN, buf, CMD_LENGTH, &length, DFLT_TIMEOUT);
273
274 if (length == 0 || ret != 0) {
275 msg_perr("Receive SPI failed\n");
276 return 1;
277 }
278
279 /* First byte indicates number of bytes transferred from upload buffer */
280 if (buf[0] != readcnt) {
281 msg_perr("Unexpected number of bytes transferred, expected %i, got %i!\n",
282 readcnt, ret);
283 return 1;
284 }
285
286 /* Actual data starts at byte number two */
287 memcpy(readarr, &buf[1], readcnt);
288 }
289
290 return 0;
291 }
292
293 /* Copied from dediprog.c */
294 /* Might be useful for other USB devices as well. static for now. */
parse_voltage(char * voltage)295 static int parse_voltage(char *voltage)
296 {
297 char *tmp = NULL;
298 int i;
299 int millivolt = 0, fraction = 0;
300
301 if (!voltage || !strlen(voltage)) {
302 msg_perr("Empty voltage= specified.\n");
303 return -1;
304 }
305 millivolt = (int)strtol(voltage, &tmp, 0);
306 voltage = tmp;
307 /* Handle "," and "." as decimal point. Everything after it is assumed
308 * to be in decimal notation.
309 */
310 if ((*voltage == '.') || (*voltage == ',')) {
311 voltage++;
312 for (i = 0; i < 3; i++) {
313 fraction *= 10;
314 /* Don't advance if the current character is invalid,
315 * but continue multiplying.
316 */
317 if ((*voltage < '0') || (*voltage > '9'))
318 continue;
319 fraction += *voltage - '0';
320 voltage++;
321 }
322 /* Throw away remaining digits. */
323 voltage += strspn(voltage, "0123456789");
324 }
325 /* The remaining string must be empty or "mV" or "V". */
326 tolower_string(voltage);
327
328 /* No unit or "V". */
329 if ((*voltage == '\0') || !strncmp(voltage, "v", 1)) {
330 millivolt *= 1000;
331 millivolt += fraction;
332 } else if (!strncmp(voltage, "mv", 2) ||
333 !strncmp(voltage, "millivolt", 9)) {
334 /* No adjustment. fraction is discarded. */
335 } else {
336 /* Garbage at the end of the string. */
337 msg_perr("Garbage voltage= specified.\n");
338 return -1;
339 }
340 return millivolt;
341 }
342
pickit2_shutdown(void * data)343 static int pickit2_shutdown(void *data)
344 {
345 struct pickit2_spi_data *pickit2_data = data;
346
347 /* Set all pins to float and turn voltages off */
348 uint8_t command[CMD_LENGTH] = {
349 CMD_EXEC_SCRIPT,
350 8,
351 SCR_SET_PINS,
352 3, /* Bit-0=1(PDC In), Bit-1=1(PGD In), Bit-2=0(PDC LL), Bit-3=0(PGD LL) */
353 SCR_SET_AUX,
354 1, /* Bit-0=1(Aux In), Bit-1=0(Aux LL) */
355 SCR_MCLR_GND_OFF,
356 SCR_VPP_OFF,
357 SCR_VDD_OFF,
358 SCR_BUSY_LED_OFF,
359 CMD_END_OF_BUFFER
360 };
361
362 int ret = pickit2_interrupt_transfer(pickit2_data->pickit2_handle, ENDPOINT_OUT, command);
363
364 if (ret != 0) {
365 msg_perr("Command Shutdown failed!\n");
366 ret = 1;
367 }
368 if (libusb_release_interface(pickit2_data->pickit2_handle, 0) != 0) {
369 msg_perr("Could not release USB interface!\n");
370 ret = 1;
371 }
372 libusb_close(pickit2_data->pickit2_handle);
373 libusb_exit(NULL);
374
375 free(data);
376 return ret;
377 }
378
379 static const struct spi_master spi_master_pickit2 = {
380 .max_data_read = 40,
381 .max_data_write = 40,
382 .command = pickit2_spi_send_command,
383 .read = default_spi_read,
384 .write_256 = default_spi_write_256,
385 .shutdown = pickit2_shutdown,
386 };
387
pickit2_spi_init(const struct programmer_cfg * cfg)388 static int pickit2_spi_init(const struct programmer_cfg *cfg)
389 {
390 uint8_t buf[CMD_LENGTH] = {
391 CMD_EXEC_SCRIPT,
392 10, /* Script length */
393 SCR_SET_PINS,
394 2, /* Bit-0=0(PDC Out), Bit-1=1(PGD In), Bit-2=0(PDC LL), Bit-3=0(PGD LL) */
395 SCR_SET_AUX,
396 0, /* Bit-0=0(Aux Out), Bit-1=0(Aux LL) */
397 SCR_VDD_ON,
398 SCR_MCLR_GND_OFF, /* Let CS# float */
399 SCR_VPP_PWM_ON,
400 SCR_VPP_ON, /* Pull CS# high */
401 SCR_BUSY_LED_ON,
402 CMD_CLR_DLOAD_BUFF,
403 CMD_CLR_ULOAD_BUFF,
404 CMD_END_OF_BUFFER
405 };
406
407 libusb_device_handle *pickit2_handle;
408 struct pickit2_spi_data *pickit2_data;
409 int spispeed_idx = 0;
410 char *param_str;
411
412 param_str = extract_programmer_param_str(cfg, "spispeed");
413 if (param_str != NULL) {
414 int i = 0;
415 for (; spispeeds[i].name; i++) {
416 if (strcasecmp(spispeeds[i].name, param_str) == 0) {
417 spispeed_idx = i;
418 break;
419 }
420 }
421 if (spispeeds[i].name == NULL) {
422 msg_perr("Error: Invalid 'spispeed' value.\n");
423 free(param_str);
424 return 1;
425 }
426 free(param_str);
427 }
428
429 int millivolt = 3500;
430 param_str = extract_programmer_param_str(cfg, "voltage");
431 if (param_str != NULL) {
432 millivolt = parse_voltage(param_str);
433 free(param_str);
434 if (millivolt < 0)
435 return 1;
436 }
437
438 if (libusb_init(NULL) < 0) {
439 msg_perr("Couldn't initialize libusb!\n");
440 return -1;
441 }
442
443 #if LIBUSB_API_VERSION < 0x01000106
444 libusb_set_debug(NULL, 3);
445 #else
446 libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO);
447 #endif
448
449 const uint16_t vid = devs_pickit2_spi[0].vendor_id;
450 const uint16_t pid = devs_pickit2_spi[0].device_id;
451 pickit2_handle = libusb_open_device_with_vid_pid(NULL, vid, pid);
452 if (pickit2_handle == NULL) {
453 msg_perr("Could not open device PICkit2!\n");
454 libusb_exit(NULL);
455 return 1;
456 }
457
458 if (libusb_set_configuration(pickit2_handle, 1) != 0) {
459 msg_perr("Could not set USB device configuration.\n");
460 libusb_close(pickit2_handle);
461 libusb_exit(NULL);
462 return 1;
463 }
464 if (libusb_claim_interface(pickit2_handle, 0) != 0) {
465 msg_perr("Could not claim USB device interface\n");
466 libusb_close(pickit2_handle);
467 libusb_exit(NULL);
468 return 1;
469 }
470
471 pickit2_data = calloc(1, sizeof(*pickit2_data));
472 if (!pickit2_data) {
473 msg_perr("Unable to allocate space for SPI master data\n");
474 libusb_close(pickit2_handle);
475 libusb_exit(NULL);
476 return 1;
477 }
478 pickit2_data->pickit2_handle = pickit2_handle;
479
480 if (pickit2_get_firmware_version(pickit2_handle))
481 goto init_err_cleanup_exit;
482
483 /* Command Set SPI Speed */
484 if (pickit2_set_spi_speed(pickit2_handle, spispeed_idx))
485 goto init_err_cleanup_exit;
486
487 /* Command Set SPI Voltage */
488 msg_pdbg("Setting voltage to %i mV.\n", millivolt);
489 if (pickit2_set_spi_voltage(pickit2_handle, millivolt) != 0)
490 goto init_err_cleanup_exit;
491
492 /* Perform basic setup.
493 * Configure pin directions and logic levels, turn Vdd on, turn busy LED on and clear buffers. */
494 if (pickit2_interrupt_transfer(pickit2_handle, ENDPOINT_OUT, buf) != 0) {
495 msg_perr("Command Setup failed!\n");
496 goto init_err_cleanup_exit;
497 }
498
499 return register_spi_master(&spi_master_pickit2, pickit2_data);
500
501 init_err_cleanup_exit:
502 pickit2_shutdown(pickit2_data);
503 return 1;
504 }
505
506 const struct programmer_entry programmer_pickit2_spi = {
507 .name = "pickit2_spi",
508 .type = USB,
509 .devs.dev = devs_pickit2_spi,
510 .init = pickit2_spi_init,
511 };
512