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