diff options
Diffstat (limited to 'mpm/tools')
-rw-r--r-- | mpm/tools/README.md | 25 | ||||
-rw-r--r-- | mpm/tools/eeprom-id.c | 5 | ||||
-rw-r--r-- | mpm/tools/eeprom-init.c | 101 | ||||
-rw-r--r-- | mpm/tools/eeprom-pids.h | 14 | ||||
-rw-r--r-- | mpm/tools/eeprom.h | 2 |
5 files changed, 113 insertions, 34 deletions
diff --git a/mpm/tools/README.md b/mpm/tools/README.md new file mode 100644 index 000000000..e756655b1 --- /dev/null +++ b/mpm/tools/README.md @@ -0,0 +1,25 @@ +# EEPROM Utilities for embedded USRP devices + +## N3x0 and E320 + +The USRP N3x0 and E320 series share the same EEPROM formats. They are initialized, +configured, and queried using the utilities in this folder (mainly, eeprom-dump +and eeprom-id to read the EEPROM, eeprom-init to configure it, eeprom-blank to +erase it, and eeprom-set-flags to configure the MCU flags). + +The N3x0 series, which has additional EEPROMs on the daughterboard, has additional +tools for those (db-dump, db-id, db-init). + +The structure of the data is fixed. A good overview of how data is stored can +be looked up either in `usrp_mpm/eeprom.py` or the structs in `eeprom.h` in this +directory. + +## X410 + +The USRP X410 uses a different EEPROM data format (tag/length/value, TLV). It is +more flexible than the format used on the previous devices. The tools to operate +on the EEPROMs for those devices are stored under `tlv_eeprom`. + +## E31x + +The USRP E31x series is not supported by these tools. diff --git a/mpm/tools/eeprom-id.c b/mpm/tools/eeprom-id.c index 24d34fdb8..aac5f12a5 100644 --- a/mpm/tools/eeprom-id.c +++ b/mpm/tools/eeprom-id.c @@ -8,10 +8,7 @@ #include <stdlib.h> #include <arpa/inet.h> #include "eeprom.h" - -#define N310_PID 0x4242 -#define N300_PID 0x4240 -#define E320_PID 0xe320 +#include "eeprom-pids.h" static void usrp_sulfur_eeprom_print_id(struct usrp_sulfur_eeprom *ep) { diff --git a/mpm/tools/eeprom-init.c b/mpm/tools/eeprom-init.c index 6ef5ccf45..b5997f222 100644 --- a/mpm/tools/eeprom-init.c +++ b/mpm/tools/eeprom-init.c @@ -5,31 +5,43 @@ // #include "eeprom.h" +#include "eeprom-pids.h" #include <stdio.h> #include <stdlib.h> -int derive_rev_compat(int rev) +int derive_rev_compat(int rev, long pid) { - if (rev > 5) - return 5; - + if (pid == E320_PID) { + if (rev >= 2) + return 2; + } else { /* N3x0 */ + if (rev > 5) + return 5; + } return rev; } -int derive_dt_compat(int rev) +int derive_dt_compat(int rev, long pid) { - /* up to rev6 they were individual dts */ - if (rev > 5) - return 5; - + if (pid == E320_PID) { + return 0; + } else { /* N3x0 */ + /* up to rev5 they were individual dts */ + if (rev > 5) + return 5; + } return rev; } -int derive_mcu_compat(int rev) +int derive_mcu_compat(int rev, long pid) { - /* up to rev6 they were individual firmware */ - if (rev > 5) - return 5; + if (pid == E320_PID) { + return 2; + } else { /* N3x0 */ + /* up to rev5 they were individual firmware */ + if (rev > 5) + return 5; + } return rev; } @@ -44,56 +56,85 @@ void usage(char *argv[]) printf("or specifying dt-compat, mcu-compat, and rev-compat explicitly:\n"); printf("$ %s 310A850 2 0c:22:cc:1a:25:c1 0c:22:cc:1a:25:c2 0c:22:cc:1a:25:c3 0x4242 5 5 5\n", argv[0]); + printf("\n"); + printf("Note: 'pid' must be specified when initializing EEPROM for the first time.\n"); + printf("Valid values are: 0x4242 (N310, N320), 0x4240 (N300), 0xe320 (E320).\n"); } int main(int argc, char *argv[]) { - struct usrp_sulfur_eeprom *ep, *ep2; + struct usrp_sulfur_eeprom *ep, *ep_stored; + u16 rev; u16 mcu_compat; u16 dt_compat; u16 rev_compat; + long pid = 0; if (argc < 6 || argc > 10) { usage(argv); return EXIT_FAILURE; } + rev = atoi(argv[2]); + + /* First, we try reading the existing EEPROM contents. This may fail, + * and that's fine. But if it works, we can use it to fill in missing + * defaults based on the existing data. + */ + ep_stored = usrp_sulfur_eeprom_from_file(NVMEM_PATH_MB); + if (!ep_stored) { + printf("-- EEPROM is either uninitialized or corrupt. Initializing all fields...\n"); + } - long pid = 0x4242; if (argc >= 7) { pid = strtol(argv[6], NULL, 0); + } else if (ep_stored) { + pid = ntohs(ep_stored->pid); + } else { + printf("-- ERROR: Cannot derive PID from existing EEPROM or command line!\n"); + return EXIT_FAILURE; + } + if (pid != N310_PID && pid != N300_PID && pid != E320_PID) { + printf("Invalid PID: %lX\n", pid); + return EXIT_FAILURE; } + /* If no MCU or DT compat specified, either use existing values, or + * derive based on rules defined at the top of this file. + */ if (argc >= 8) { dt_compat = strtol(argv[7], NULL, 0); printf("dt_compat=%u\n", dt_compat); + } else if (ep_stored) { + dt_compat = ntohs(ep_stored->dt_compat); + printf("dt_compat=%u\n", dt_compat); } else { - dt_compat = derive_dt_compat(atoi(argv[2])); + dt_compat = derive_dt_compat(rev, pid); } if (argc >= 9) { mcu_compat = strtol(argv[8], NULL, 0); printf("mcu_compat=%u\n", mcu_compat); + } else if (ep_stored) { + mcu_compat = ntohs(ep_stored->mcu_compat); + printf("mcu_compat=%u\n", mcu_compat); } else { - mcu_compat = derive_mcu_compat(atoi(argv[2])); + mcu_compat = derive_mcu_compat(rev, pid); } if (argc >= 10) { rev_compat = strtol(argv[9], NULL, 0); printf("rev_compat=%u\n", rev_compat); + } else if (ep_stored && rev == ep_stored->rev) { + rev_compat = ntohs(ep_stored->rev_compat); + printf("rev_compat=%u\n", rev_compat); } else { - rev_compat = derive_rev_compat(atoi(argv[2])); + rev_compat = derive_rev_compat(rev, pid); } - if (pid < 0 || pid > 0xFFFF) { - printf("Invalid PID: %lX\n", pid); - return EXIT_FAILURE; - } + if (ep_stored) + free(ep_stored); - /* If no MCU or DT compat specified, derive based on rule up there, - * i.e. everything newer than 5 will be 5, assuming we don't change - * anything software visible anymore - */ - ep = usrp_sulfur_eeprom_new(NULL, (u16) pid, atoi(argv[2]), argv[1], + ep = usrp_sulfur_eeprom_new(NULL, (u16) pid, rev, argv[1], argv[3], argv[4], argv[5], dt_compat, mcu_compat, rev_compat); @@ -102,7 +143,7 @@ int main(int argc, char *argv[]) free(ep); printf("-- Reading back \n"); - ep2 = usrp_sulfur_eeprom_from_file(NVMEM_PATH_MB); - usrp_sulfur_eeprom_print(ep2); - free(ep2); + ep_stored = usrp_sulfur_eeprom_from_file(NVMEM_PATH_MB); + usrp_sulfur_eeprom_print(ep_stored); + free(ep_stored); } diff --git a/mpm/tools/eeprom-pids.h b/mpm/tools/eeprom-pids.h new file mode 100644 index 000000000..c980c12ed --- /dev/null +++ b/mpm/tools/eeprom-pids.h @@ -0,0 +1,14 @@ +// +// Copyright 2022 Ettus Research, a National Instruments Brand +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#ifndef EEPROM_PIDS_H +#define EEPROM_PIDS_H + +#define N310_PID 0x4242 +#define N300_PID 0x4240 +#define E320_PID 0xe320 + +#endif /* EEPROM_PIDS_H */ diff --git a/mpm/tools/eeprom.h b/mpm/tools/eeprom.h index 39301327f..47b6b3f71 100644 --- a/mpm/tools/eeprom.h +++ b/mpm/tools/eeprom.h @@ -21,6 +21,8 @@ typedef uint8_t u8; #define NVMEM_PATH_SLOT_B "/sys/bus/nvmem/devices/10-00500/nvmem" #define NVMEM_PATH_MB "/sys/bus/nvmem/devices/2-00500/nvmem" +/* Despite the "sulfur" name, this also applies for E320 ("neon") + */ struct usrp_sulfur_eeprom { u32 magic; u32 version; |