blob: 5351fbd0b31fb1738770f00a7ab56e3b5c3941a3 [file] [log] [blame]
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001/*
Stefan Reinauer5cf0da72015-08-17 15:22:20 -07002 * Copyright 2012-2015 Google Inc.
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
Stefan Reinauer0ce691f2012-08-03 14:20:24 -070012 */
13
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
Martin Roth92c453b2015-09-01 10:35:02 -060017#include <strings.h>
Stefan Reinauer0ce691f2012-08-03 14:20:24 -070018#include <getopt.h>
Simon Glass98cd62c2018-12-26 14:31:20 -070019#include <unistd.h>
Stefan Reinauer8db88b92020-12-17 19:22:13 -080020#include <ctype.h>
Stefan Reinauerdb126f42019-11-18 18:25:45 -080021#include <dirent.h>
22#include <errno.h>
23#include <sys/stat.h>
24#include <wordexp.h>
25
Stefan Reinauerc566d202015-08-25 09:52:42 -070026#include "em100.h"
Martin Roth4203a382014-08-02 08:14:37 -060027
Stefan Reinauerafe03252020-11-21 16:03:59 -080028#define MAX_USB_ERRORS 10
29
Stefan Reinauerdb126f42019-11-18 18:25:45 -080030TFILE *configs;
31char *database_version;
Stefan Reinauerb20610e2019-12-06 11:14:33 -080032int debug = 0;
Stefan Reinauerdfb107d2020-12-10 19:22:40 -080033int address_mode = 3;
Stefan Reinauer0ce691f2012-08-03 14:20:24 -070034
Stefan Reinauered59fc82020-11-21 16:11:40 -080035volatile sig_atomic_t exit_requested = 0;
Stefan Reinauer71367472020-11-18 21:12:20 -080036static struct em100 em100_state;
Patrick Georgif3558c62014-10-28 18:16:57 +010037
Stefan Reinauer6a5ed5b2019-11-19 14:52:16 -080038static void exit_handler(int sig __unused)
39{
Stefan Reinauered59fc82020-11-21 16:11:40 -080040 exit_requested = 1;
Patrick Georgif3558c62014-10-28 18:16:57 +010041}
42
Aaron Durbin637fe482012-10-17 17:39:19 -050043struct em100_hold_pin_states {
44 const char *description;
45 int value;
46};
47
Stefan Reinauerfba00632012-10-18 09:17:00 -070048static const struct em100_hold_pin_states hold_pin_states[] = {
Aaron Durbin637fe482012-10-17 17:39:19 -050049 { "FLOAT", 0x2 },
50 { "LOW", 0x0 },
51 { "INPUT", 0x3 },
52 { NULL, 0x0 },
53};
54
Stefan Reinauer54f91d92015-08-18 12:00:07 -070055/* High Level functions */
56
Stefan Reinauerb82d79b2015-08-18 11:14:33 -070057static int set_state(struct em100 *em100, int run)
58{
Martin Rothda63eb72015-09-11 12:16:23 -060059 int retval = write_fpga_register(em100, 0x28, run & 1);
60
61 if (retval)
62 printf("%s EM100Pro\n", run ? "Started" : "Stopped");
63
64 return retval;
65}
66
67static void get_current_state(struct em100 *em100)
68{
69 uint16_t state;
70 if (read_fpga_register(em100, 0x28, &state))
71 printf("EM100Pro currently %s\n", state ? "running" : "stopped");
72 else
73 printf("EM100Pro state unknown\n");
74}
75
Duncan Laurief4361562020-04-15 12:54:51 -070076static int set_address_mode(struct em100 *em100, int mode)
77{
78 int retval;
79
80 if (mode < 3 || mode > 4) {
81 printf("Invalid address mode: %d\n", mode);
82 return -1;
83 }
84
85 retval = write_fpga_register(em100, 0x4f, mode == 4);
86 if (retval)
87 printf("Enabled %d byte address mode\n", mode);
88 else
89 printf("Failed to enable %d byte address mode\n", mode);
90
91 return retval;
92}
93
Stefan Reinauer79533882019-11-22 00:57:29 -080094static const char *get_pin_string(int pin) {
Martin Rothda63eb72015-09-11 12:16:23 -060095 switch (pin) {
96 case 0:
97 return ("low");
98 break;
99 case 2:
100 return ("float");
101 break;
102 case 3:
103 return ("input");
104 break;
105 }
106 return ("unknown");
107}
108
109static void get_current_pin_state(struct em100 *em100)
110{
111 uint16_t val = 0xffff;
112 read_fpga_register(em100, 0x2a, &val);
113 printf("EM100Pro hold pin currently %s\n", get_pin_string(val));
Stefan Reinauerb82d79b2015-08-18 11:14:33 -0700114}
115
116static int set_hold_pin_state(struct em100 *em100, int pin_state)
117{
118 uint16_t val;
119
Martin Rothb54d6ba2015-09-29 14:49:37 -0600120 /* Read and acknowledge hold pin state setting bit 2 of pin state response. */
Stefan Reinauerb82d79b2015-08-18 11:14:33 -0700121 if (!read_fpga_register(em100, 0x2a, &val)) {
122 printf("Couldn't get hold pin state.\n");
123 return 0;
124 }
125 write_fpga_register(em100, 0x2a, (1 << 2) | val);
126
127
128 if (!read_fpga_register(em100, 0x2a, &val)) {
129 printf("Couldn't get hold pin state.\n");
130 return 0;
131 }
132
133 /* Now set desired pin state. */
134 write_fpga_register(em100, 0x2a, pin_state);
135
136 /* Read the pin state. */
137 if (!read_fpga_register(em100, 0x2a, &val)) {
138 printf("Couldn't get hold pin state.\n");
139 return 0;
140 }
141
142 if (val != pin_state) {
Martin Rothb54d6ba2015-09-29 14:49:37 -0600143 printf("Invalid pin state response: 0x%04x %s"
144 " (expected 0x%04x %s)\n", val,
145 get_pin_string(val), pin_state,
146 get_pin_string(pin_state));
Stefan Reinauerb82d79b2015-08-18 11:14:33 -0700147 return 0;
148 }
149
Martin Rothda63eb72015-09-11 12:16:23 -0600150 printf("Hold pin state set to %s\n", get_pin_string(val));
Stefan Reinauerb82d79b2015-08-18 11:14:33 -0700151 return 1;
152}
153
154static int set_hold_pin_state_from_str(struct em100 *em100, const char *state)
155{
156 int pin_state;
157 const struct em100_hold_pin_states *s = &hold_pin_states[0];
158
159 while (s->description != NULL) {
Martin Rothf4f581a2015-09-18 11:39:27 -0600160 if (!strcasecmp(s->description, state))
Stefan Reinauerb82d79b2015-08-18 11:14:33 -0700161 break;
162 s++;
163 }
164 if (s->description == NULL) {
165 printf("Invalid hold pin state: %s\n", state);
166 return 0;
167 }
168 pin_state = s->value;
169
170 return set_hold_pin_state(em100, pin_state);
171}
172
Simon Glass98cd62c2018-12-26 14:31:20 -0700173static int set_fpga_voltage(struct em100 *em100, int voltage_code)
174{
175 int val;
176
177 if (!fpga_reconfigure(em100)) {
178 printf("Couldn't reconfigure FPGA.\n");
179 return 0;
180 }
181
182 if (!fpga_set_voltage(em100, voltage_code)) {
183 printf("Couldn't set FPGA voltage.\n");
184 return 0;
185 }
186
187 /* Must wait 2s before issuing any other USB comand */
188 sleep(2);
189
190 if (!fpga_get_voltage(em100, &val)) {
191 printf("Couldn't get FPGA voltage.\n");
192 return 0;
193 }
194
195 if (val != voltage_code) {
196 printf("Invalid voltage response: %#x (expected %#x)\n", val,
197 voltage_code);
198 return 0;
199 }
200
201 printf("Voltage set to %s\n", val == 18 ? "1.8" : "3.3");
202
203 return 1;
204}
205
206static int set_fpga_voltage_from_str(struct em100 *em100,
207 const char *voltage_str)
208{
209 int voltage_code;
210
211 if (!strcmp(voltage_str, "3.3"))
212 voltage_code = 33;
213 else if (!strcmp(voltage_str, "1.8"))
214 voltage_code = 18;
215 else {
216 printf("Invalid voltage, use 1.8 or 3.3.\n");
217 return 0;
218 }
219
220 return set_fpga_voltage(em100, voltage_code);
221}
222
Stefan Reinauer52875112015-08-20 13:57:20 -0700223/**
Stefan Reinauer98eb7532019-11-13 18:42:07 -0800224 * get_device_info: fetch device's serial number and hardware version
Stefan Reinauer52875112015-08-20 13:57:20 -0700225 * @param em100: initialized em100 device structure
226 */
Stefan Reinauer98eb7532019-11-13 18:42:07 -0800227static int get_device_info(struct em100 *em100)
Stefan Reinauer52875112015-08-20 13:57:20 -0700228{
229 unsigned char data[256];
230 if (read_spi_flash_page(em100, 0x1fff00, data)) {
231 em100->serialno = (data[5] << 24) | (data[4] << 16) | \
232 (data[3] << 8) | data[2];
Stefan Reinauer98eb7532019-11-13 18:42:07 -0800233 em100->hwversion = data[1];
Stefan Reinauer52875112015-08-20 13:57:20 -0700234 return 1;
235 }
236 return 0;
237}
238
Stefan Reinauere636d2a2015-08-28 16:58:57 -0700239static int set_serialno(struct em100 *em100, unsigned int serialno)
240{
241 unsigned char data[512];
242 unsigned int old_serialno;
243
244 if (!read_spi_flash_page(em100, 0x1fff00, data))
245 return 0;
246
247 old_serialno = (data[5] << 24) | (data[4] << 16) | \
248 (data[3] << 8) | data[2];
249
250 if (old_serialno == serialno) {
251 printf("Serial number unchanged.\n");
252 return 1;
253 }
254
255 data[2] = serialno;
256 data[3] = serialno >> 8;
257 data[4] = serialno >> 16;
258 data[5] = serialno >> 24;
259
260 if (old_serialno != 0xffffffff) {
261 /* preserve magic */
262 read_spi_flash_page(em100, 0x1f0000, data + 256);
263 /* Unlock and erase sector. Reading
264 * the SPI flash ID is requires to
265 * actually unlock the chip.
266 */
267 unlock_spi_flash(em100);
268 get_spi_flash_id(em100);
269 erase_spi_flash_sector(em100, 0x1f);
270 /* write back magic */
271 write_spi_flash_page(em100, 0x1f0000, data + 256);
272 }
273
274 if (!write_spi_flash_page(em100, 0x1fff00, data)) {
275 printf("Error: Could not write SPI flash.\n");
276 return 0;
277 }
Stefan Reinauer98eb7532019-11-13 18:42:07 -0800278
279 /* Re-read serial number */
280 get_device_info(em100);
Stefan Reinauere636d2a2015-08-28 16:58:57 -0700281 if (em100->serialno != 0xffffffff)
Stefan Reinauerbd8e1d02019-11-28 15:48:51 -0800282 printf("New serial number: %s%06d\n",
283 em100->hwversion == HWVERSION_EM100PRO_EARLY ? "DP" : "EM",
284 em100->serialno);
Stefan Reinauere636d2a2015-08-28 16:58:57 -0700285 else
286 printf("New serial number: N.A.\n");
287
288 return 1;
289}
290
Stefan Reinauer14d35122015-09-03 16:02:55 -0700291static int em100_debug(struct em100 *em100)
292{
293 int i;
Stefan Reinauer828687b2020-11-21 17:27:05 -0800294 printf("Voltages:\n");
Stefan Reinauer14d35122015-09-03 16:02:55 -0700295 set_led(em100, both_off);
296 printf(" 1.2V: %dmV\n", get_voltage(em100, in_v1_2));
297 printf(" E_VCC: %dmV\n", get_voltage(em100, in_e_vcc));
298 set_led(em100, both_on);
299 printf(" REF+: %dmV\n", get_voltage(em100, in_ref_plus));
300 printf(" REF-: %dmV\n", get_voltage(em100, in_ref_minus));
301 set_led(em100, red_on);
302 printf(" Buffer VCC: %dmV\n", get_voltage(em100, in_buffer_vcc));
303 printf(" Trig VCC: %dmV\n", get_voltage(em100, in_trigger_vcc));
304 set_led(em100, both_on);
305 printf(" RST VCC: %dmV\n", get_voltage(em100, in_reset_vcc));
306 printf(" 3.3V: %dmV\n", get_voltage(em100, in_v3_3));
307 set_led(em100, red_on);
308 printf(" Buffer 3.3V: %dmV\n", get_voltage(em100, in_buffer_v3_3));
309 printf(" 5V: %dmV\n", get_voltage(em100, in_v5));
310 set_led(em100, green_on);
311 printf("\nFPGA registers:");
312 for (i = 0; i < 256; i += 2) {
313 uint16_t val;
314 if ((i % 16) == 0)
315 printf("\n %04x: ", i);
316 if (read_fpga_register(em100, i, &val))
317 printf("%04x ", val);
318 else
319 printf("XXXX ");
320 }
321
322 printf("\n");
323 return 1;
324}
325
Stefan Reinauer52875112015-08-20 13:57:20 -0700326static int check_status(struct em100 *em100)
327{
328 int spi_flash_id;
329
330 spi_flash_id = get_spi_flash_id(em100);
Stefan Reinauer22340e82015-08-24 12:26:20 -0700331 /* Check for Micron (formerly Numonyx, formerly STMicro)
332 * M25P16 spi flash part
333 */
Stefan Reinauer52875112015-08-20 13:57:20 -0700334 if (spi_flash_id == 0x202015)
335 return 1;
336 return 0;
337}
338
Martin Rothb54d6ba2015-09-29 14:49:37 -0600339static int em100_init(struct em100 *em100, libusb_context *ctx,
340 libusb_device_handle *dev)
Stefan Reinauer9fbe20d2015-09-09 12:21:00 -0700341{
Stefan Reinauer3e8fdf12020-11-19 16:38:26 -0800342 if (libusb_set_auto_detach_kernel_driver(dev, 1) != LIBUSB_SUCCESS) {
343 printf("Can't detach kernel driver.\n");
344 return 0;
Stefan Reinauer9fbe20d2015-09-09 12:21:00 -0700345 }
346
Stefan Reinauer848fe722020-11-19 16:39:45 -0800347 if (libusb_claim_interface(dev, 0)) {
Stefan Reinauer9fbe20d2015-09-09 12:21:00 -0700348 printf("Could not claim interface.\n");
349 return 0;
350 }
351
352 em100->dev = dev;
353 em100->ctx = ctx;
354
355 if (!check_status(em100)) {
356 printf("Device status unknown.\n");
357 return 0;
358 }
359
360 if (!get_version(em100)) {
361 printf("Failed to fetch version information.\n");
362 return 0;
363 }
364
Stefan Reinauer98eb7532019-11-13 18:42:07 -0800365 if (!get_device_info(em100)) {
366 printf("Failed to fetch serial number and hardware version.\n");
Stefan Reinauer9fbe20d2015-09-09 12:21:00 -0700367 return 0;
368 }
369
370 return 1;
371}
372
Martin Rothb54d6ba2015-09-29 14:49:37 -0600373static int em100_attach(struct em100 *em100, int bus, int device,
Stefan Reinauer79533882019-11-22 00:57:29 -0800374 uint32_t serial_number)
Stefan Reinauer52875112015-08-20 13:57:20 -0700375{
Stefan Reinauerc601b342015-09-08 12:30:03 -0700376 libusb_device_handle *dev = NULL;
Stefan Reinauer52875112015-08-20 13:57:20 -0700377 libusb_context *ctx = NULL;
378
379 if (libusb_init(&ctx) < 0) {
380 printf("Could not init libusb.\n");
381 return 0;
382 }
383
Stefan Reinauer220a0992018-06-09 19:23:58 +0000384#if LIBUSB_API_VERSION < 0x01000106
Stefan Reinauerd73d50b2020-11-19 16:37:07 -0800385 libusb_set_debug(ctx, LIBUSB_LOG_LEVEL_INFO);
Stefan Reinauer220a0992018-06-09 19:23:58 +0000386#else
Stefan Reinauerd73d50b2020-11-19 16:37:07 -0800387 libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO);
Stefan Reinauer220a0992018-06-09 19:23:58 +0000388#endif
Stefan Reinauer52875112015-08-20 13:57:20 -0700389
Stefan Reinauerc601b342015-09-08 12:30:03 -0700390 if ((!bus || !device) && !serial_number) {
Stefan Reinauer081bb822015-09-03 16:26:10 -0700391 dev = libusb_open_device_with_vid_pid(ctx, 0x4b4, 0x1235);
392 } else {
393 libusb_device **devs, *d;
394 int i;
395
396 if (libusb_get_device_list(ctx, &devs) < 0) {
397 printf("Could not find USB devices.\n");
398 return 0;
399 }
400
401 for (i = 0; (d = devs[i]) != NULL; i++) {
402 if ((bus > 0 && (libusb_get_bus_number(d) == bus)) &&
Martin Rothb54d6ba2015-09-29 14:49:37 -0600403 (device > 0 &&
404 (libusb_get_device_address(d) == device))) {
405
Stefan Reinauer081bb822015-09-03 16:26:10 -0700406 struct libusb_device_descriptor desc;
407 libusb_get_device_descriptor(d, &desc);
Martin Rothb54d6ba2015-09-29 14:49:37 -0600408 if (desc.idVendor == 0x4b4 &&
409 desc.idProduct == 0x1235) {
Stefan Reinauer081bb822015-09-03 16:26:10 -0700410 if (libusb_open(d, &dev)) {
Martin Rothb54d6ba2015-09-29 14:49:37 -0600411 printf("Couldn't open EM100pro"
412 " device.\n");
Stefan Reinauer081bb822015-09-03 16:26:10 -0700413 return 0;
414 }
415 } else {
Martin Rothb54d6ba2015-09-29 14:49:37 -0600416 printf("USB device on bus %03d:%02d is"
417 " not an EM100pro.\n",
418 bus, device);
Stefan Reinauer081bb822015-09-03 16:26:10 -0700419 return 0;
420 }
421 break;
422 }
Stefan Reinauerc601b342015-09-08 12:30:03 -0700423 if (serial_number) {
424 struct libusb_device_descriptor desc;
425 libusb_get_device_descriptor(d, &desc);
Martin Rothb54d6ba2015-09-29 14:49:37 -0600426 if (desc.idVendor == 0x4b4 &&
427 desc.idProduct == 0x1235) {
Stefan Reinauerc601b342015-09-08 12:30:03 -0700428 if (libusb_open(d, &dev)) {
Martin Rothb54d6ba2015-09-29 14:49:37 -0600429 printf("Couldn't open EM100pro"
430 " device.\n");
Stefan Reinauerc601b342015-09-08 12:30:03 -0700431 continue;
432 }
433 if (!dev) {
Martin Rothb54d6ba2015-09-29 14:49:37 -0600434 printf("Couldn't open EM100pro"
435 " device.\n");
Stefan Reinauerc601b342015-09-08 12:30:03 -0700436 continue;
437 }
Stefan Reinauerc601b342015-09-08 12:30:03 -0700438
Stefan Reinauer9fbe20d2015-09-09 12:21:00 -0700439 if (em100_init(em100, ctx, dev) &&
Martin Rothb54d6ba2015-09-29 14:49:37 -0600440 (serial_number == em100->serialno))
Stefan Reinauerc601b342015-09-08 12:30:03 -0700441 break;
Stefan Reinauerc601b342015-09-08 12:30:03 -0700442
Stefan Reinauerc601b342015-09-08 12:30:03 -0700443 libusb_release_interface(dev, 0);
444 libusb_close(dev);
445 em100->dev = NULL;
446 em100->ctx = NULL;
447 em100->serialno = 0;
448 dev = NULL;
449 }
450 }
Stefan Reinauer081bb822015-09-03 16:26:10 -0700451 }
Stefan Reinauerc601b342015-09-08 12:30:03 -0700452
Stefan Reinauer081bb822015-09-03 16:26:10 -0700453 libusb_free_device_list(devs, 1);
Stefan Reinauer52875112015-08-20 13:57:20 -0700454 }
455
Stefan Reinauer8b337782015-12-09 16:17:29 -0800456 if (!dev) {
457 if (bus && device)
458 printf("Could not find EM100pro at %03d:%03d.\n", bus, device);
459 else if (serial_number)
Stefan Reinauer163dbc12019-11-21 00:04:58 -0800460 printf("Could not find EM100pro with serial number EM%06d.\n",
Stefan Reinauer8b337782015-12-09 16:17:29 -0800461 serial_number);
462 else
463 printf("Could not find EM100pro device.\n");
464
Stefan Reinauer52875112015-08-20 13:57:20 -0700465 return 0;
466 }
467
Stefan Reinauer9fbe20d2015-09-09 12:21:00 -0700468 return em100_init(em100, ctx, dev);
Stefan Reinauer52875112015-08-20 13:57:20 -0700469}
470
471static int em100_detach(struct em100 *em100)
472{
473 if (libusb_release_interface(em100->dev, 0) != 0) {
Stefan Reinauerc601b342015-09-08 12:30:03 -0700474 printf("Releasing interface failed.\n");
Stefan Reinauer52875112015-08-20 13:57:20 -0700475 return 1;
476 }
477
478 libusb_close(em100->dev);
479 libusb_exit(em100->ctx);
480
481 return 0;
482}
483
Stefan Reinauer7eda75e2015-09-03 16:32:13 -0700484static int em100_list(void)
485{
486 struct em100 em100;
487 libusb_device **devs, *dev;
488 libusb_context *ctx = NULL;
489 int i, count = 0;
490
491 if (libusb_init(&ctx) < 0) {
492 printf("Could not init libusb.\n");
493 return 0;
494 }
495
Stefan Reinauer220a0992018-06-09 19:23:58 +0000496#if LIBUSB_API_VERSION < 0x01000106
Stefan Reinauer7eda75e2015-09-03 16:32:13 -0700497 libusb_set_debug(ctx, 3);
Stefan Reinauer220a0992018-06-09 19:23:58 +0000498#else
499 libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, 3);
500#endif
Stefan Reinauer7eda75e2015-09-03 16:32:13 -0700501
502 if (libusb_get_device_list(ctx, &devs) < 0) {
503 printf("Could not find USB devices.\n");
504 return 0;
505 }
506
507 for (i = 0; (dev = devs[i]) != NULL; i++) {
508 struct libusb_device_descriptor desc;
509 libusb_get_device_descriptor(dev, &desc);
510 if (desc.idVendor != 0x4b4 || desc.idProduct != 0x1235)
511 continue;
512
Martin Roth0c6a4542015-09-09 12:08:13 -0600513 if (!em100_attach(&em100, libusb_get_bus_number(dev),
514 libusb_get_device_address(dev), 0)) {
Martin Rothb54d6ba2015-09-29 14:49:37 -0600515 printf("Could not read from EM100 at Bus %03d Device"
516 " %03d\n", libusb_get_bus_number(dev),
Martin Roth0c6a4542015-09-09 12:08:13 -0600517 libusb_get_device_address(dev));
518 continue;
519 }
Stefan Reinauerbd8e1d02019-11-28 15:48:51 -0800520 printf(" Bus %03d Device %03d: EM100pro %s%06d\n",
Stefan Reinauer7eda75e2015-09-03 16:32:13 -0700521 libusb_get_bus_number(dev),
522 libusb_get_device_address(dev),
Stefan Reinauerbd8e1d02019-11-28 15:48:51 -0800523 em100.hwversion == HWVERSION_EM100PRO_EARLY ? "DP" : "EM",
Stefan Reinauer7eda75e2015-09-03 16:32:13 -0700524 em100.serialno);
525 em100_detach(&em100);
526 count++;
527 }
528 if (count == 0)
529 printf("No EM100pro devices found.\n");
530 libusb_exit(ctx);
531 return 1;
532}
533
Stefan Reinauer52875112015-08-20 13:57:20 -0700534static int set_chip_type(struct em100 *em100, const chipdesc *desc)
535{
536 unsigned char cmd[16];
537 /* result counts unsuccessful send_cmd()s.
538 * These are then converted in a boolean success value
539 */
540 int result = 0;
541 int i;
Simon Glass0008e672019-01-04 13:59:55 -0700542 int fpga_voltage, chip_voltage = 0;
543 int req_voltage = 0;
Stefan Reinauer52875112015-08-20 13:57:20 -0700544
Stefan Reinauerdb126f42019-11-18 18:25:45 -0800545 printf("Configuring SPI flash chip emulation.\n");
Stefan Reinauer52875112015-08-20 13:57:20 -0700546
547 memset(cmd, 0, 16);
548
Stefan Reinauer53cf2342015-08-28 16:56:40 -0700549 fpga_voltage = em100->fpga & 0x8000 ? 1800 : 3300;
550
551 for (i = 0; i < desc->init_len; i++) {
552 if(desc->init[i][0] != 0x11 || desc->init[i][1] != 0x04)
553 continue;
554
555 chip_voltage = (desc->init[i][2] << 8) | desc->init[i][3];
556
557 switch (chip_voltage) {
558 case 1601: /* 1.65V-2V */
559 case 1800:
560 if (fpga_voltage == 3300)
Simon Glass0008e672019-01-04 13:59:55 -0700561 req_voltage = 18;
Stefan Reinauer53cf2342015-08-28 16:56:40 -0700562 break;
563 case 2500: /* supported by both 1.8V and 3.3V FPGA */
564 break;
565 case 3300:
566 if (fpga_voltage == 1800)
Simon Glass0008e672019-01-04 13:59:55 -0700567 req_voltage = 33;
Stefan Reinauer53cf2342015-08-28 16:56:40 -0700568 }
569 break;
570 }
571
Simon Glass0008e672019-01-04 13:59:55 -0700572 if (req_voltage) {
573 if (!set_fpga_voltage(em100, req_voltage)) {
574 printf("Error: The current FPGA firmware (%.1fV) does "
575 "not support %s %s (%.1fV)\n",
576 (float)fpga_voltage / 1000, desc->vendor,
577 desc->name, (float)chip_voltage / 1000);
578 return 0;
579 }
Stefan Reinauer53cf2342015-08-28 16:56:40 -0700580 }
581
Stefan Reinauer52875112015-08-20 13:57:20 -0700582 for (i = 0; i < desc->init_len; i++) {
583 memcpy(&cmd[0], &desc->init[i][0], BYTES_PER_INIT_ENTRY);
584 result += !send_cmd(em100->dev, cmd);
585 }
586
Martin Rothdfdff3e2015-09-18 09:42:03 -0600587 /*
588 * Set FPGA registers as the Dediprog software does:
589 * 0xc4 is set every time the chip type is updated
590 * 0x10 and 0x81 are set once when the software is initialized.
591 */
592 write_fpga_register(em100, 0xc4, 0x01);
593 write_fpga_register(em100, 0x10, 0x00);
594 write_fpga_register(em100, 0x81, 0x00);
595
Stefan Reinauer52875112015-08-20 13:57:20 -0700596 return !result;
597}
598
Patrick Rudolph8b557a92019-10-10 10:15:14 +0200599/**
600 * Searches for a specific FPGA register in the chip initialisation
601 * sequence and returns the value in out.
602 *
603 * @reg1: e.g. FPGA write command (0x23)
604 * @reg2: e.g. FPGA register
605 *
606 * Returns 0 on success.
607 */
608static int get_chip_init_val(const chipdesc *desc,
609 const uint8_t reg1,
610 const uint8_t reg2,
611 uint16_t *out)
612{
613 int i;
614
615 for (i = 0; i < desc->init_len; i++) {
616 if (desc->init[i][0] == reg1 && desc->init[i][1] == reg2) {
617 *out = (desc->init[i][2] << 8) | desc->init[i][3];
618 return 0;
619 }
620 }
621
622 return 1;
623}
624
Stefan Reinauerdb126f42019-11-18 18:25:45 -0800625typedef struct {
626 uint16_t venid;
627 uint16_t devid;
628 int found;
629 chipdesc chip;
630} vendev_t;
631
632static int get_chip_type_entry(char *name __unused, TFILE *dcfg, void *data, int ok __unused)
633{
634 uint16_t comp;
635 chipdesc chip;
636
637 vendev_t *v = (vendev_t *)data;
638
639 parse_dcfg(&chip, dcfg);
640
641 if (get_chip_init_val(&chip, 0x23, FPGA_REG_DEVID, &comp) || v->devid != comp)
642 return 0;
643 if (get_chip_init_val(&chip, 0x23, FPGA_REG_VENDID, &comp) || v->venid != comp)
644 return 0;
645 v->found = 1;
646 v->chip = chip;
647 return 1;
648}
649
Patrick Rudolph8b557a92019-10-10 10:15:14 +0200650/**
651 * Tries to identify the currently emulated SPI flash by looking at
652 * known registers in the FPGA and matches those bits with the
653 * chip initialisation sequence.
654 *
655 * Returns 0 on success.
656 */
Stefan Reinauerdb126f42019-11-18 18:25:45 -0800657static int get_chip_type(struct em100 *em100, chipdesc *out)
Patrick Rudolph8b557a92019-10-10 10:15:14 +0200658{
Stefan Reinauerdb126f42019-11-18 18:25:45 -0800659 vendev_t v;
Patrick Rudolph8b557a92019-10-10 10:15:14 +0200660
661 /* Read manufacturer and vendor id from FPGA */
Stefan Reinauerdb126f42019-11-18 18:25:45 -0800662 if (!read_fpga_register(em100, FPGA_REG_VENDID, &v.venid))
Patrick Rudolph8b557a92019-10-10 10:15:14 +0200663 return 1;
Stefan Reinauerdb126f42019-11-18 18:25:45 -0800664 if (!read_fpga_register(em100, FPGA_REG_DEVID, &v.devid))
Patrick Rudolph8b557a92019-10-10 10:15:14 +0200665 return 1;
666
Stefan Reinauerdb126f42019-11-18 18:25:45 -0800667 tar_for_each(configs, get_chip_type_entry, (void *)&v);
668 if (!v.found)
Patrick Rudolph8b557a92019-10-10 10:15:14 +0200669 return 1;
670
Stefan Reinauerdb126f42019-11-18 18:25:45 -0800671 *out = v.chip;
672
673 return 0;
674}
675
676static int list_chips_entry(char *name __unused, TFILE *file, void *data __unused, int ok __unused)
677{
678 static chipdesc chip;
679 /* Is the file a dcfg file? Then print the name, otherwise skip. */
680
681 if (!parse_dcfg(&chip, file))
682 printf(" • %s %s\n", chip.vendor, chip.name);
Patrick Rudolph8b557a92019-10-10 10:15:14 +0200683
684 return 0;
685}
686
Stefan Reinauere67e8922019-11-21 15:30:46 -0800687static chipdesc *setup_chips(const char *desiredchip)
688{
Stefan Reinauerdb126f42019-11-18 18:25:45 -0800689 static chipdesc chip;
Stefan Reinauer32c7e7b2019-12-02 10:43:05 -0800690 char *configs_name = get_em100_file("configs.tar.xz");
691 configs = tar_load_compressed(configs_name);
692 free(configs_name);
Stefan Reinauerdb126f42019-11-18 18:25:45 -0800693 if (!configs) {
Stefan Reinauerd05f9602020-01-08 10:32:56 -0800694 printf("Can't find chip configs in $EM100_HOME/configs.tar.xz.\n"
695 "Please run: em100 --update-files.\n");
Stefan Reinauerdb126f42019-11-18 18:25:45 -0800696 return NULL;
697 }
698
699 TFILE *version = tar_find(configs,"configs/VERSION", 1);
700 if (!version) {
701 printf("Can't find VERSION of chip configs.\n");
702 return NULL;
703 }
704 database_version = (char *)version->address;
705 tar_close(version);
706
Stefan Reinauere67e8922019-11-21 15:30:46 -0800707 if (desiredchip) {
Stefan Reinauerdb126f42019-11-18 18:25:45 -0800708 char chipname[256];
709 sprintf(chipname, "configs/%s.cfg", desiredchip);
710 TFILE *dcfg = tar_find(configs, chipname, 0);
711 if (!dcfg) {
712 printf("Supported chips:\n\n");
713 tar_for_each(configs, list_chips_entry, NULL);
714 printf("\nCould not find a chip matching '%s' to be emulated.\n",
Stefan Reinauere67e8922019-11-21 15:30:46 -0800715 desiredchip);
Stefan Reinauere67e8922019-11-21 15:30:46 -0800716 return NULL;
717 }
Stefan Reinauerdb126f42019-11-18 18:25:45 -0800718 parse_dcfg(&chip, dcfg);
719 tar_close(dcfg);
720 return &chip;
Stefan Reinauere67e8922019-11-21 15:30:46 -0800721 }
Stefan Reinauerdb126f42019-11-18 18:25:45 -0800722 return NULL;
723}
724
725static char *get_em100_home(void)
726{
727 static char directory[FILENAME_BUFFER_SIZE] = "\0";
728
729 if (directory[0] != 0)
730 return directory;
731
732 /* find out file */
733 wordexp_t p;
734 char *em100_home = getenv("EM100_HOME");
735 if (em100_home)
736 wordexp("$EM100_HOME/", &p, 0);
737 else
738 wordexp("$HOME/.em100/", &p, 0);
739
740 strncpy(directory, p.we_wordv[0], FILENAME_BUFFER_SIZE - 1);
741 wordfree(&p);
742
743 DIR *dir = opendir(directory);
744 if (dir) {
Stefan Reinauer7243d622019-12-04 14:32:02 -0800745 /* success */
746 closedir(dir);
Stefan Reinauerdb126f42019-11-18 18:25:45 -0800747 } else if (errno == ENOENT) {
Stefan Reinauer62f2aa62019-12-02 11:22:26 -0800748 if (mkdir(directory, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
749 perror(directory);
750 directory[0]=0;
751 return NULL;
752 }
Stefan Reinauerdb126f42019-11-18 18:25:45 -0800753 } else {
754 perror("EM100_HOME inaccessible");
755 directory[0]=0;
756 return NULL;
757 }
758
759 return directory;
760}
761
Stefan Reinauer79533882019-11-22 00:57:29 -0800762char *get_em100_file(const char *name)
Stefan Reinauerdb126f42019-11-18 18:25:45 -0800763{
Stefan Reinauera115fc72019-12-02 10:58:42 -0800764 char file[FILENAME_BUFFER_SIZE + 1];
Stefan Reinauerdb126f42019-11-18 18:25:45 -0800765 strncpy(file, get_em100_home(), FILENAME_BUFFER_SIZE);
766 strncat(file, name, FILENAME_BUFFER_SIZE - strlen(file) - 1);
767 return strdup(file);
Stefan Reinauere67e8922019-11-21 15:30:46 -0800768}
769
Stefan Reinauer0ce691f2012-08-03 14:20:24 -0700770static const struct option longopts[] = {
771 {"set", 1, 0, 'c'},
772 {"download", 1, 0, 'd'},
Tsung Ho Wu9fda6742019-01-15 10:56:56 -0800773 {"start-address", 1, 0, 'a'},
Duncan Laurief4361562020-04-15 12:54:51 -0700774 {"address-mode", 1, 0, 'm'},
Stefan Reinauer0ce691f2012-08-03 14:20:24 -0700775 {"start", 0, 0, 'r'},
776 {"stop", 0, 0, 's'},
777 {"verify", 0, 0, 'v'},
Aaron Durbin637fe482012-10-17 17:39:19 -0500778 {"holdpin", 1, 0, 'p'},
Stefan Reinauer14d35122015-09-03 16:02:55 -0700779 {"debug", 0, 0, 'D'},
Stefan Reinauer0ce691f2012-08-03 14:20:24 -0700780 {"help", 0, 0, 'h'},
Stefan Reinauera5b46d42015-09-03 16:14:25 -0700781 {"trace", 0, 0, 't'},
Martin Roth712262a2015-09-18 14:01:18 -0600782 {"offset", 1, 0, 'O'},
Stefan Reinauere636d2a2015-08-28 16:58:57 -0700783 {"set-serialno", 1, 0, 'S'},
Stefan Reinauera2b67d32015-09-01 16:30:43 -0700784 {"firmware-update", 1, 0, 'F'},
785 {"firmware-dump", 1, 0, 'f'},
Stefan Reinauera9278a92015-09-01 16:16:27 -0700786 {"firmware-write", 1, 0, 'g'},
Stefan Reinauer7eda75e2015-09-03 16:32:13 -0700787 {"device", 1, 0, 'x'},
788 {"list-devices", 0, 0, 'l'},
Stefan Reinauerdfd556c2019-11-20 17:57:40 -0800789 {"update-files", 0, 0, 'U'},
Stefan Reinauer3b921082019-11-26 16:56:26 -0800790 {"terminal", 0, 0, 'T'},
Stefan Reinauercafd1512020-12-11 17:36:28 -0800791 {"traceconsole", 0, 0, 'R'},
792 {"length", 1, 0, 'L'},
Stefan Reinauer146eeba2020-12-17 19:26:02 -0800793 {"brief", 0, 0, 'b'},
Stefan Reinauer3b921082019-11-26 16:56:26 -0800794 {"compatible", 0, 0, 'C'},
Stefan Reinauer0ce691f2012-08-03 14:20:24 -0700795 {NULL, 0, 0, 0}
796};
797
Stefan Reinauera5b46d42015-09-03 16:14:25 -0700798static void usage(char *name)
Stefan Reinauer0ce691f2012-08-03 14:20:24 -0700799{
Stefan Reinauera5b46d42015-09-03 16:14:25 -0700800 printf("em100: EM100pro command line utility\n\nExample:\n"
Martin Rothb54d6ba2015-09-29 14:49:37 -0600801 " %s --stop --set M25P80 -d file.bin -v --start -t -O 0xfff00000\n"
Stefan Reinauera5b46d42015-09-03 16:14:25 -0700802 "\nUsage:\n"
Martin Rothb54d6ba2015-09-29 14:49:37 -0600803 " -c|--set CHIP: select chip emulation\n"
Duncan Laurie578f0682016-12-06 11:38:28 -0800804 " -d|--download FILE: download FILE into EM100pro\n"
Tsung Ho Wu9fda6742019-01-15 10:56:56 -0800805 " -a|--start address: only works with -d (E.g. -d file.bin -a 0x300000)\n"
Duncan Laurief4361562020-04-15 12:54:51 -0700806 " -m|--address-mode MODE: force 3 or 4 byte address mode\n"
Patrick Rudolph9a56e462019-10-15 09:05:45 +0200807 " -u|--upload FILE: upload from EM100pro into FILE\n"
Martin Rothb54d6ba2015-09-29 14:49:37 -0600808 " -r|--start: em100 shall run\n"
809 " -s|--stop: em100 shall stop\n"
810 " -v|--verify: verify EM100 content matches the file\n"
811 " -t|--trace: trace mode\n"
812 " -O|--offset HEX_VAL: address offset for trace mode\n"
813 " -T|--terminal: terminal mode\n"
Stefan Reinauercafd1512020-12-11 17:36:28 -0800814 " -R|--traceconsole: trace console mode\n"
815 " -L|--length HEX_VAL: length of buffer for traceconsole mode\n"
Stefan Reinauer146eeba2020-12-17 19:26:02 -0800816 " -b|--brief: brief mode for traces\n"
Stefan Reinauera27fa812019-11-24 21:58:02 -0800817 " -F|--firmware-update FILE|auto: update EM100pro firmware (dangerous)\n"
Martin Rothb54d6ba2015-09-29 14:49:37 -0600818 " -f|--firmware-dump FILE: export raw EM100pro firmware to file\n"
819 " -g|--firmware-write FILE: export EM100pro firmware to DPFW file\n"
820 " -S|--set-serialno NUM: set serial number to NUM\n"
Simon Glass98cd62c2018-12-26 14:31:20 -0700821 " -V|--set-voltage [1.8|3.3] switch FPGA voltage\n"
Stefan Reinauera5b46d42015-09-03 16:14:25 -0700822 " -p|--holdpin [LOW|FLOAT|INPUT]: set the hold pin state\n"
Martin Rothb54d6ba2015-09-29 14:49:37 -0600823 " -x|--device BUS:DEV use EM100pro on USB bus/device\n"
Stefan Reinauer163dbc12019-11-21 00:04:58 -0800824 " -x|--device EMxxxxxx use EM100pro with serial no EMxxxxxx\n"
Martin Rothb54d6ba2015-09-29 14:49:37 -0600825 " -l|--list-devices list all connected EM100pro devices\n"
Stefan Reinauerdfd556c2019-11-20 17:57:40 -0800826 " -U|--update-files update device (chip) and firmware database\n"
Stefan Reinauer3b921082019-11-26 16:56:26 -0800827 " -C|--compatible enable compatibility mode (patch image for EM100Pro)\n"
Martin Rothb54d6ba2015-09-29 14:49:37 -0600828 " -D|--debug: print debug information.\n"
829 " -h|--help: this help text\n\n",
830 name);
Stefan Reinauer0ce691f2012-08-03 14:20:24 -0700831}
832
Stefan Reinauer0ce691f2012-08-03 14:20:24 -0700833int main(int argc, char **argv)
834{
835 int opt, idx;
836 const char *desiredchip = NULL;
Stefan Reinauere636d2a2015-08-28 16:58:57 -0700837 const char *serialno = NULL;
Duncan Laurie578f0682016-12-06 11:38:28 -0800838 const char *filename = NULL, *read_filename = NULL;
Stefan Reinauera2b67d32015-09-01 16:30:43 -0700839 const char *firmware_in = NULL, *firmware_out = NULL;
Aaron Durbin637fe482012-10-17 17:39:19 -0500840 const char *holdpin = NULL;
Stefan Reinauer0ce691f2012-08-03 14:20:24 -0700841 int do_start = 0, do_stop = 0;
Stefan Reinauercafd1512020-12-11 17:36:28 -0800842 int verify = 0, trace = 0, terminal=0, traceconsole=0;
Stefan Reinauerb20610e2019-12-06 11:14:33 -0800843 int compatibility = 0;
Stefan Reinauer081bb822015-09-03 16:26:10 -0700844 int bus = 0, device = 0;
Stefan Reinauera9278a92015-09-01 16:16:27 -0700845 int firmware_is_dpfw = 0;
Stefan Reinauerc601b342015-09-08 12:30:03 -0700846 unsigned int serial_number = 0;
Stefan Reinauercafd1512020-12-11 17:36:28 -0800847 unsigned long address_offset = 0, address_length = 0;
Stefan Reinauer79533882019-11-22 00:57:29 -0800848 unsigned int spi_start_address = 0;
Simon Glass98cd62c2018-12-26 14:31:20 -0700849 const char *voltage = NULL;
Stefan Reinauer7ea18c02020-09-18 20:53:11 -0700850 struct sigaction signal_action;
Stefan Reinauer71367472020-11-18 21:12:20 -0800851 struct em100 *em100 = &em100_state;
Stefan Reinauerc601b342015-09-08 12:30:03 -0700852
Stefan Reinauer146eeba2020-12-17 19:26:02 -0800853 while ((opt = getopt_long(argc, argv, "c:d:a:m:u:rsvtO:F:f:g:S:V:p:DCx:lUhTRL:b",
Stefan Reinauer0ce691f2012-08-03 14:20:24 -0700854 longopts, &idx)) != -1) {
855 switch (opt) {
856 case 'c':
857 desiredchip = optarg;
858 break;
859 case 'd':
Stefan Reinauer7a22c452020-12-17 19:21:04 -0800860 if(access(optarg, F_OK) == 0)
861 filename = optarg;
862 else
863 printf("Can't open '%s'.\n", optarg);
Stefan Reinauer0ce691f2012-08-03 14:20:24 -0700864 break;
Tsung Ho Wu9fda6742019-01-15 10:56:56 -0800865 case 'a':
Stefan Reinauer79533882019-11-22 00:57:29 -0800866 sscanf(optarg, "%x", &spi_start_address);
867 printf("SPI address: 0x%08x\n", spi_start_address);
Tsung Ho Wu9fda6742019-01-15 10:56:56 -0800868 break;
Duncan Laurief4361562020-04-15 12:54:51 -0700869 case 'm':
870 sscanf(optarg, "%d", &address_mode);
871 break;
Duncan Laurie578f0682016-12-06 11:38:28 -0800872 case 'u':
873 read_filename = optarg;
874 break;
Simon Glass98cd62c2018-12-26 14:31:20 -0700875 case 'V':
876 voltage = optarg;
877 break;
Aaron Durbin637fe482012-10-17 17:39:19 -0500878 case 'p':
879 holdpin = optarg;
880 break;
Stefan Reinauer0ce691f2012-08-03 14:20:24 -0700881 case 'r':
882 do_start = 1;
883 break;
884 case 's':
Aaron Durbinf5587022012-10-16 15:37:12 -0500885 do_stop = 1;
Stefan Reinauer0ce691f2012-08-03 14:20:24 -0700886 break;
887 case 'v':
888 verify = 1;
889 break;
Patrick Georgif3558c62014-10-28 18:16:57 +0100890 case 't':
891 trace = 1;
892 break;
Martin Roth712262a2015-09-18 14:01:18 -0600893 case 'O':
894 sscanf(optarg, "%lx", &address_offset);
895 printf("Address offset: 0x%08lx\n", address_offset);
896 break;
Martin Rothdfdff3e2015-09-18 09:42:03 -0600897 case 'T':
898 terminal = 1;
899 break;
Stefan Reinauere636d2a2015-08-28 16:58:57 -0700900 case 'S':
901 serialno = optarg;
Martin Rothe6835192015-09-09 12:15:05 -0600902 break;
Stefan Reinauer14d35122015-09-03 16:02:55 -0700903 case 'D':
904 debug=1;
Stefan Reinauere636d2a2015-08-28 16:58:57 -0700905 break;
Stefan Reinauera2b67d32015-09-01 16:30:43 -0700906 case 'F':
907 firmware_in = optarg;
908 break;
909 case 'f':
910 firmware_out = optarg;
911 break;
Stefan Reinauera9278a92015-09-01 16:16:27 -0700912 case 'g':
913 firmware_out = optarg;
914 firmware_is_dpfw = 1;
915 break;
Stefan Reinauer7eda75e2015-09-03 16:32:13 -0700916 case 'x':
Stefan Reinauer8db88b92020-12-17 19:22:13 -0800917 if ((toupper(optarg[0]) == 'D' && toupper(optarg[1]) == 'P') ||
918 (toupper(optarg[0]) == 'E' && toupper(optarg[1]) == 'M'))
Stefan Reinauerc601b342015-09-08 12:30:03 -0700919 sscanf(optarg + 2, "%d", &serial_number);
920 else
921 sscanf(optarg, "%d:%d", &bus, &device);
Stefan Reinauer7eda75e2015-09-03 16:32:13 -0700922 break;
923 case 'l':
924 em100_list();
925 return 0;
Stefan Reinauerdfd556c2019-11-20 17:57:40 -0800926 case 'U':
927 update_all_files();
928 return 0;
Stefan Reinauercafd1512020-12-11 17:36:28 -0800929 case 'R':
930 traceconsole = 1;
931 break;
932 case 'L':
933 sscanf(optarg, "%lx", &address_length);
934 break;
Stefan Reinauer146eeba2020-12-17 19:26:02 -0800935 case 'b':
936 trace_brief = 1;
937 break;
Stefan Reinauer3b921082019-11-26 16:56:26 -0800938 case 'C':
939 compatibility = 1;
940 break;
Stefan Reinauera5b46d42015-09-03 16:14:25 -0700941 default:
Stefan Reinauer0ce691f2012-08-03 14:20:24 -0700942 case 'h':
Stefan Reinauera5b46d42015-09-03 16:14:25 -0700943 usage(argv[0]);
Stefan Reinauer0ce691f2012-08-03 14:20:24 -0700944 return 0;
945 }
946 }
947
Stefan Reinauer71367472020-11-18 21:12:20 -0800948 if (!em100_attach(em100, bus, device, serial_number)) {
Stefan Reinauer0ce691f2012-08-03 14:20:24 -0700949 return 1;
950 }
951
Stefan Reinauere67e8922019-11-21 15:30:46 -0800952 const chipdesc *chip = setup_chips(desiredchip);
Stefan Reinauer003ac422020-11-21 20:28:17 -0800953 if (desiredchip && !chip) {
954 em100_detach(em100);
Stefan Reinauere67e8922019-11-21 15:30:46 -0800955 return 1;
Stefan Reinauer003ac422020-11-21 20:28:17 -0800956 }
Stefan Reinauere67e8922019-11-21 15:30:46 -0800957
Stefan Reinauer7ea18c02020-09-18 20:53:11 -0700958 /* Set up signal handler. This is used for two reasons:
959 * 1) to create a way to cleanly exit trace mode.
960 * 2) to make sure that the em100 is not left in an improper state
Stefan Reinauer2634d3b2020-11-18 21:33:20 -0800961 * when receiving SIGINT/SIGTERM for other reasons during operation.
962 * In this second case, we just ignore the first signal until em100
963 * naturally terminates or receives a second signal. This is OK
964 * because the utility is short-running in nature.
Stefan Reinauer7ea18c02020-09-18 20:53:11 -0700965 */
966 signal_action.sa_handler = exit_handler;
967 signal_action.sa_flags = 0;
968 sigemptyset(&signal_action.sa_mask);
969 sigaction(SIGINT, &signal_action, NULL);
Stefan Reinauer2634d3b2020-11-18 21:33:20 -0800970 sigaction(SIGTERM, &signal_action, NULL);
Stefan Reinauerae881352021-03-08 10:57:38 -0800971 sigaction(SIGHUP, &signal_action, NULL);
Stefan Reinauer937401e2019-11-24 13:55:24 -0800972
Stefan Reinauer71367472020-11-18 21:12:20 -0800973 if (em100->hwversion == HWVERSION_EM100PRO || em100->hwversion == HWVERSION_EM100PRO_EARLY) {
974 printf("MCU version: %d.%02d\n", em100->mcu >> 8, em100->mcu & 0xff);
Stefan Reinauer14deb032015-08-28 16:33:00 -0700975 /* While the Dediprog software for Windows will refuse to work
976 * with 1.8V chips on older FPGA versions, it does not
977 * specifically output a voltage when reporting the FPGA
978 * version. We emulate this behavior here. Version 0.51 is
979 * known to behave the old way, 0.75 is behaving the new
980 * way.
981 */
Stefan Reinauer71367472020-11-18 21:12:20 -0800982 if (em100->fpga > 0x0033) /* 0.51 */
Stefan Reinauer937401e2019-11-24 13:55:24 -0800983 printf("FPGA version: %d.%02d (%s)\n",
Stefan Reinauer71367472020-11-18 21:12:20 -0800984 em100->fpga >> 8 & 0x7f, em100->fpga & 0xff,
985 em100->fpga & 0x8000 ? "1.8V" : "3.3V");
Stefan Reinauer937401e2019-11-24 13:55:24 -0800986 else
Stefan Reinauer71367472020-11-18 21:12:20 -0800987 printf("FPGA version: %d.%02d\n", em100->fpga >> 8,
988 em100->fpga & 0xff);
Stefan Reinauer937401e2019-11-24 13:55:24 -0800989 } else {/* EM100Pro-G2 */
Stefan Reinauer71367472020-11-18 21:12:20 -0800990 printf("MCU version: %d.%d\n", em100->mcu >> 8, em100->mcu & 0xff);
Stefan Reinauer937401e2019-11-24 13:55:24 -0800991 printf("FPGA version: %d.%03d\n",
Stefan Reinauer71367472020-11-18 21:12:20 -0800992 em100->fpga >> 8 & 0x7f, em100->fpga & 0xff);
Stefan Reinauer14deb032015-08-28 16:33:00 -0700993 }
Stefan Reinauer937401e2019-11-24 13:55:24 -0800994
Stefan Reinauer71367472020-11-18 21:12:20 -0800995 printf("Hardware version: %u\n", em100->hwversion);
Stefan Reinauer14deb032015-08-28 16:33:00 -0700996
Stefan Reinauer71367472020-11-18 21:12:20 -0800997 if (em100->serialno != 0xffffffff)
Stefan Reinauerbd8e1d02019-11-28 15:48:51 -0800998 printf("Serial number: %s%06d\n",
Stefan Reinauer71367472020-11-18 21:12:20 -0800999 em100->hwversion == HWVERSION_EM100PRO_EARLY ? "DP" : "EM", em100->serialno);
Stefan Reinauer14deb032015-08-28 16:33:00 -07001000 else
1001 printf("Serial number: N.A.\n");
Stefan Reinauerdb126f42019-11-18 18:25:45 -08001002 printf("SPI flash database: %s\n", database_version);
Stefan Reinauer71367472020-11-18 21:12:20 -08001003 get_current_state(em100);
1004 get_current_pin_state(em100);
Martin Rothda63eb72015-09-11 12:16:23 -06001005 printf("\n");
1006
1007 if (debug) {
Stefan Reinauer71367472020-11-18 21:12:20 -08001008 em100_debug(em100);
Stefan Reinauer14d35122015-09-03 16:02:55 -07001009 }
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001010
Stefan Reinauera2b67d32015-09-01 16:30:43 -07001011 if (firmware_in) {
Stefan Reinauer71367472020-11-18 21:12:20 -08001012 firmware_update(em100, firmware_in, verify);
1013 return em100_detach(em100);
Stefan Reinauera2b67d32015-09-01 16:30:43 -07001014 }
1015
1016 if (firmware_out) {
Stefan Reinauer71367472020-11-18 21:12:20 -08001017 firmware_dump(em100, firmware_out, firmware_is_dpfw);
1018 return em100_detach(em100);
Stefan Reinauera2b67d32015-09-01 16:30:43 -07001019 }
1020
Stefan Reinauere636d2a2015-08-28 16:58:57 -07001021 if (serialno) {
Martin Roth12e58862015-09-09 12:23:31 -06001022 int offset = 0;
1023 /* if the user specified a serial containing DP, skip that */
1024 if ((serialno[0] == 'D' || serialno[0] == 'd') &&
1025 (serialno[1] == 'P' || serialno[1] == 'p'))
1026 offset = 2;
Stefan Reinauer163dbc12019-11-21 00:04:58 -08001027 /* if the user specified a serial containing EM, skip that */
1028 if ((serialno[0] == 'E' || serialno[0] == 'e') &&
1029 (serialno[1] == 'M' || serialno[1] == 'm'))
1030 offset = 2;
Martin Roth12e58862015-09-09 12:23:31 -06001031
1032 if (sscanf(serialno + offset, "%d", &serial_number) != 1)
Stefan Reinauere636d2a2015-08-28 16:58:57 -07001033 printf("Error: Can't parse serial number '%s'\n",
1034 serialno);
1035 else
Stefan Reinauer71367472020-11-18 21:12:20 -08001036 set_serialno(em100, serial_number);
Stefan Reinauere636d2a2015-08-28 16:58:57 -07001037
Stefan Reinauer71367472020-11-18 21:12:20 -08001038 return em100_detach(em100);
Stefan Reinauere636d2a2015-08-28 16:58:57 -07001039 }
1040
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001041 if (do_stop) {
Stefan Reinauer71367472020-11-18 21:12:20 -08001042 set_state(em100, 0);
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001043 }
1044
1045 if (desiredchip) {
Stefan Reinauer71367472020-11-18 21:12:20 -08001046 if (!set_chip_type(em100, chip)) {
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001047 printf("Failed configuring chip type.\n");
Stefan Reinauer003ac422020-11-21 20:28:17 -08001048 em100_detach(em100);
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001049 return 0;
1050 }
Stefan Reinauerdb126f42019-11-18 18:25:45 -08001051 printf("Chip set to %s %s.\n", chip->vendor, chip->name);
Duncan Laurief4361562020-04-15 12:54:51 -07001052
1053 /* Automatically enable 4 byte address mode for chips >16MB
1054 * unless specified by the user on the command line.
1055 */
1056 if (!address_mode && chip->size > (16 * 1024 * 1024)) {
Stefan Reinauer71367472020-11-18 21:12:20 -08001057 set_address_mode(em100, 4);
Duncan Laurief4361562020-04-15 12:54:51 -07001058 }
1059 }
1060
1061 if (address_mode) {
Stefan Reinauer71367472020-11-18 21:12:20 -08001062 if (set_address_mode(em100, address_mode) < 0) {
Stefan Reinauer003ac422020-11-21 20:28:17 -08001063 em100_detach(em100);
Duncan Laurief4361562020-04-15 12:54:51 -07001064 return 1;
1065 }
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001066 }
1067
Simon Glass98cd62c2018-12-26 14:31:20 -07001068 if (voltage) {
Stefan Reinauer71367472020-11-18 21:12:20 -08001069 if (!set_fpga_voltage_from_str(em100, voltage)) {
Simon Glass98cd62c2018-12-26 14:31:20 -07001070 printf("Failed configuring FPGA voltage.\n");
Stefan Reinauer003ac422020-11-21 20:28:17 -08001071 em100_detach(em100);
Simon Glass98cd62c2018-12-26 14:31:20 -07001072 return 1;
1073 }
1074 }
1075
Aaron Durbin637fe482012-10-17 17:39:19 -05001076 if (holdpin) {
Stefan Reinauer71367472020-11-18 21:12:20 -08001077 if (!set_hold_pin_state_from_str(em100, holdpin)) {
Aaron Durbin637fe482012-10-17 17:39:19 -05001078 printf("Failed configuring hold pin state.\n");
Stefan Reinauer003ac422020-11-21 20:28:17 -08001079 em100_detach(em100);
Aaron Durbin637fe482012-10-17 17:39:19 -05001080 return 0;
1081 }
1082 }
1083
Duncan Laurie578f0682016-12-06 11:38:28 -08001084 if (read_filename) {
Patrick Rudolph8b557a92019-10-10 10:15:14 +02001085 int maxlen = 0x4000000; /* largest size - 64MB */
1086
1087 if (!desiredchip) {
1088 /* Read configured SPI emulation from EM100 */
Stefan Reinauerdb126f42019-11-18 18:25:45 -08001089 chipdesc emulated_chip;
Patrick Rudolph8b557a92019-10-10 10:15:14 +02001090
Stefan Reinauer71367472020-11-18 21:12:20 -08001091 if (!get_chip_type(em100, &emulated_chip)) {
Stefan Reinauerdb126f42019-11-18 18:25:45 -08001092 printf("Configured to emulate %dkB chip\n", emulated_chip.size / 1024);
1093 maxlen = emulated_chip.size;
Patrick Rudolph8b557a92019-10-10 10:15:14 +02001094 }
1095 } else {
1096 maxlen = chip->size;
1097 }
1098
Duncan Laurie578f0682016-12-06 11:38:28 -08001099 void *data = malloc(maxlen);
1100 if (data == NULL) {
1101 printf("FATAL: couldn't allocate memory\n");
Stefan Reinauer003ac422020-11-21 20:28:17 -08001102 em100_detach(em100);
Duncan Laurie578f0682016-12-06 11:38:28 -08001103 return 1;
1104 }
1105 FILE *fdata = fopen(read_filename, "wb");
1106 if (!fdata) {
1107 perror("Could not open download file");
1108 free(data);
Stefan Reinauer003ac422020-11-21 20:28:17 -08001109 em100_detach(em100);
Duncan Laurie578f0682016-12-06 11:38:28 -08001110 return 1;
1111 }
1112
Stefan Reinauer71367472020-11-18 21:12:20 -08001113 read_sdram(em100, data, 0x00000000, maxlen);
Duncan Laurie578f0682016-12-06 11:38:28 -08001114
1115 int length = fwrite(data, maxlen, 1, fdata);
1116 fclose(fdata);
1117 free(data);
1118
1119 if (length != 1) {
1120 printf("FATAL: failed to write");
Stefan Reinauer003ac422020-11-21 20:28:17 -08001121 em100_detach(em100);
Duncan Laurie578f0682016-12-06 11:38:28 -08001122 return 1;
1123 }
1124 }
1125
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001126 if (filename) {
Stefan Reinauer79533882019-11-22 00:57:29 -08001127 unsigned int maxlen = desiredchip ? chip->size : 0x4000000; /* largest size - 64MB */
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001128 void *data = malloc(maxlen);
Tsung Ho Wu9fda6742019-01-15 10:56:56 -08001129 int done;
1130 void *readback = NULL;
1131
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001132 if (data == NULL) {
1133 printf("FATAL: couldn't allocate memory\n");
Stefan Reinauer003ac422020-11-21 20:28:17 -08001134 em100_detach(em100);
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001135 return 1;
1136 }
1137 FILE *fdata = fopen(filename, "rb");
1138 if (!fdata) {
1139 perror("Could not open upload file");
Stefan Reinauer0bced2e2015-09-08 12:58:56 -07001140 free(data);
Stefan Reinauer003ac422020-11-21 20:28:17 -08001141 em100_detach(em100);
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001142 return 1;
1143 }
1144
Stefan Reinauer79533882019-11-22 00:57:29 -08001145 unsigned int length = 0;
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001146 while ((!feof(fdata)) && (length < maxlen)) {
1147 int blocksize = 65536;
Martin Rothb54d6ba2015-09-29 14:49:37 -06001148 length += blocksize * fread(data+length, blocksize, 1,
1149 fdata);
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001150 }
1151 fclose(fdata);
1152
1153 if (length > maxlen) {
1154 printf("FATAL: length > maxlen\n");
Stefan Reinauer0bced2e2015-09-08 12:58:56 -07001155 free(data);
Stefan Reinauer003ac422020-11-21 20:28:17 -08001156 em100_detach(em100);
Stefan Reinauer0bced2e2015-09-08 12:58:56 -07001157 return 1;
1158 }
1159
1160 if (length == 0) {
1161 printf("FATAL: No file to upload.\n");
1162 free(data);
Stefan Reinauer003ac422020-11-21 20:28:17 -08001163 em100_detach(em100);
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001164 return 1;
1165 }
1166
Tsung Ho Wu9fda6742019-01-15 10:56:56 -08001167 if (desiredchip && (length != (chip->size - spi_start_address)) )
1168 {
1169 printf("FATAL: file size does not match to chip size.\n");
1170 free(data);
Stefan Reinauer003ac422020-11-21 20:28:17 -08001171 em100_detach(em100);
Tsung Ho Wu9fda6742019-01-15 10:56:56 -08001172 return 1;
1173 }
1174
Stefan Reinauer3b921082019-11-26 16:56:26 -08001175 if (compatibility)
Stefan Reinauer71367472020-11-18 21:12:20 -08001176 autocorrect_image(em100, data, length);
Stefan Reinauer3b921082019-11-26 16:56:26 -08001177
Tsung Ho Wu9fda6742019-01-15 10:56:56 -08001178 if (spi_start_address) {
1179 readback = malloc(maxlen);
Jacob Garberca833ce2019-08-16 15:04:50 -06001180 if (readback == NULL) {
Tsung Ho Wu9fda6742019-01-15 10:56:56 -08001181 printf("FATAL: couldn't allocate memory(size: %x)\n", maxlen);
Jacob Garberca833ce2019-08-16 15:04:50 -06001182 free(data);
Stefan Reinauer003ac422020-11-21 20:28:17 -08001183 em100_detach(em100);
Tsung Ho Wu9fda6742019-01-15 10:56:56 -08001184 return 1;
1185 }
Stefan Reinauer71367472020-11-18 21:12:20 -08001186 done = read_sdram(em100, readback, 0, maxlen);
Jacob Garberb4a35cd2019-08-16 15:10:51 -06001187 if (done) {
1188 memcpy((unsigned char*)readback + spi_start_address, data, length);
Stefan Reinauer71367472020-11-18 21:12:20 -08001189 write_sdram(em100, (unsigned char*)readback, 0x00000000, maxlen);
Jacob Garberb4a35cd2019-08-16 15:10:51 -06001190 } else {
1191 printf("Error: sdram readback failed\n");
1192 }
Tsung Ho Wu9fda6742019-01-15 10:56:56 -08001193 free(readback);
1194 } else {
Stefan Reinauer71367472020-11-18 21:12:20 -08001195 write_sdram(em100, (unsigned char*)data, 0x00000000, length);
Tsung Ho Wu9fda6742019-01-15 10:56:56 -08001196 }
1197
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001198 if (verify) {
Tsung Ho Wu9fda6742019-01-15 10:56:56 -08001199 readback = malloc(length);
Jacob Garberca833ce2019-08-16 15:04:50 -06001200 if (readback == NULL) {
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001201 printf("FATAL: couldn't allocate memory\n");
Jacob Garberca833ce2019-08-16 15:04:50 -06001202 free(data);
Stefan Reinauer003ac422020-11-21 20:28:17 -08001203 em100_detach(em100);
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001204 return 1;
1205 }
Stefan Reinauer71367472020-11-18 21:12:20 -08001206 done = read_sdram(em100, readback, spi_start_address, length);
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001207 if (done && (memcmp(data, readback, length) == 0))
1208 printf("Verify: PASS\n");
Ryan O'Leary5c72c8d2020-08-27 15:14:16 -07001209 else {
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001210 printf("Verify: FAIL\n");
Ryan O'Leary5c72c8d2020-08-27 15:14:16 -07001211 free(readback);
1212 free(data);
Stefan Reinauer71367472020-11-18 21:12:20 -08001213 em100_detach(em100);
Ryan O'Leary5c72c8d2020-08-27 15:14:16 -07001214 return 1;
1215 }
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001216 free(readback);
1217 }
1218
1219 free(data);
1220 }
1221
1222 if (do_start) {
Stefan Reinauer71367472020-11-18 21:12:20 -08001223 set_state(em100, 1);
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001224 }
1225
Stefan Reinauercafd1512020-12-11 17:36:28 -08001226 if (trace || terminal || traceconsole) {
Stefan Reinauerafe03252020-11-21 16:03:59 -08001227 int usb_errors = 0;
1228
Stefan Reinauer71367472020-11-18 21:12:20 -08001229 if ((holdpin == NULL) && (!set_hold_pin_state(em100, 3))) {
Stefan Reinauercf24ed72015-08-24 12:21:45 -07001230 printf("Error: Failed to set EM100 to input\n");
Stefan Reinauer003ac422020-11-21 20:28:17 -08001231 em100_detach(em100);
Patrick Georgif3558c62014-10-28 18:16:57 +01001232 return 1;
1233 }
Martin Rothdfdff3e2015-09-18 09:42:03 -06001234
Martin Rothb54d6ba2015-09-29 14:49:37 -06001235 if (!do_start && !do_stop)
Stefan Reinauer71367472020-11-18 21:12:20 -08001236 set_state(em100, 1);
Patrick Georgif3558c62014-10-28 18:16:57 +01001237
Martin Rothdfdff3e2015-09-18 09:42:03 -06001238 printf ("Starting ");
1239
Stefan Reinauercafd1512020-12-11 17:36:28 -08001240 if (trace || traceconsole) {
Stefan Reinauer71367472020-11-18 21:12:20 -08001241 reset_spi_trace(em100);
Martin Rothdfdff3e2015-09-18 09:42:03 -06001242 printf("trace%s", terminal ? " & " : "");
1243 }
1244
1245 if (terminal) {
Stefan Reinauer71367472020-11-18 21:12:20 -08001246 init_spi_terminal(em100);
Martin Rothdfdff3e2015-09-18 09:42:03 -06001247 printf("terminal");
1248 }
1249
Stefan Reinauer3d08fa92020-12-22 17:17:29 -08001250 printf(". Press CTRL-C to exit.\n\n");
1251 fflush(stdout);
Patrick Georgif3558c62014-10-28 18:16:57 +01001252
Stefan Reinauered59fc82020-11-21 16:11:40 -08001253 while (!exit_requested && usb_errors < MAX_USB_ERRORS) {
Stefan Reinauerdb543822020-12-11 16:29:44 -08001254 int ret;
Stefan Reinauercafd1512020-12-11 17:36:28 -08001255
1256 if (traceconsole)
1257 ret = read_spi_trace_console(em100, address_offset, address_length);
1258 else if (trace)
Stefan Reinauerdb543822020-12-11 16:29:44 -08001259 ret = read_spi_trace(em100, terminal, address_offset);
Stefan Reinauercafd1512020-12-11 17:36:28 -08001260 else if (terminal)
Stefan Reinauerdb543822020-12-11 16:29:44 -08001261 ret = read_spi_terminal(em100, 0);
Stefan Reinauercafd1512020-12-11 17:36:28 -08001262
Stefan Reinauerdb543822020-12-11 16:29:44 -08001263 if (ret == 0)
1264 usb_errors++;
Stefan Reinauercafd1512020-12-11 17:36:28 -08001265 if (ret < 0)
1266 break;
Patrick Georgif3558c62014-10-28 18:16:57 +01001267 }
Stefan Reinauerafe03252020-11-21 16:03:59 -08001268 if (usb_errors >= MAX_USB_ERRORS)
1269 printf("Error: Bailed out with too many USB errors.\n");
Patrick Georgif3558c62014-10-28 18:16:57 +01001270
Martin Rothb54d6ba2015-09-29 14:49:37 -06001271 if (!do_start && !do_stop)
Stefan Reinauer71367472020-11-18 21:12:20 -08001272 set_state(em100, 0);
Stefan Reinauer003ac422020-11-21 20:28:17 -08001273
Martin Rothdfdff3e2015-09-18 09:42:03 -06001274 if (trace)
Stefan Reinauer71367472020-11-18 21:12:20 -08001275 reset_spi_trace(em100);
Patrick Georgif3558c62014-10-28 18:16:57 +01001276
Stefan Reinauer71367472020-11-18 21:12:20 -08001277 if ((holdpin == NULL) && (!set_hold_pin_state(em100, 2))) {
Stefan Reinauercf24ed72015-08-24 12:21:45 -07001278 printf("Error: Failed to set EM100 to float\n");
Stefan Reinauer003ac422020-11-21 20:28:17 -08001279 em100_detach(em100);
Patrick Georgif3558c62014-10-28 18:16:57 +01001280 return 1;
1281 }
1282 }
1283
Stefan Reinauer71367472020-11-18 21:12:20 -08001284 return em100_detach(em100);
Stefan Reinauer0ce691f2012-08-03 14:20:24 -07001285}