aboutsummaryrefslogtreecommitdiffstats
path: root/mpm/tools
diff options
context:
space:
mode:
Diffstat (limited to 'mpm/tools')
-rw-r--r--mpm/tools/README.md25
-rw-r--r--mpm/tools/eeprom-id.c5
-rw-r--r--mpm/tools/eeprom-init.c101
-rw-r--r--mpm/tools/eeprom-pids.h14
-rw-r--r--mpm/tools/eeprom.h2
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;