diff options
author | Martin Braun <martin.braun@ettus.com> | 2022-01-28 11:56:11 +0100 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2022-02-24 14:00:07 -0600 |
commit | 8ca640b922700276abb86adde1b5ad46f3d2af07 (patch) | |
tree | 13190bed0163c696039cd00be4e33b9a79036d4e /mpm | |
parent | 1d0806092491dc172ba31312840df02d8ec0b11a (diff) | |
download | uhd-8ca640b922700276abb86adde1b5ad46f3d2af07.tar.gz uhd-8ca640b922700276abb86adde1b5ad46f3d2af07.tar.bz2 uhd-8ca640b922700276abb86adde1b5ad46f3d2af07.zip |
mpm: eeprom: Fix default values in EEPROM utilities
When executing eeprom-init on E320 (which was originally written for
N310), it would use defaults from N310, potentially causing issues.
These issues would have arisen if we letter-revved the E320 one more
time (because at rev 5, N310 had a compatibility cutover).
Summary of changes:
- eeprom-init will now read values *not* given on the command line from
the existing content of the EEPROM, if it contains valid data. This
means that DT, MCU, and rev compat values will no longer get
auto-derived if the EEPROM already contained "good" values.
- If the EEPROM is empty or corrupted, eeprom-init will no longer run if
the pid value is not provided. This is to avoid N310 defaults being
written to E320 EEPROMs.
- A README is added to explain which devices use which utilities.
- PID checks are more strict now. It is unlikely we'll build new devices
using the old EEPROM format (prior to TLV), so we can check
specifically for E320, N3x0.
- The hard-coded list of PIDs for the EEPROM tools are moved to
a central location (eeprom-pids.h).
- The code to derive values for DT/MCU/rev compat from the rev is now
pid-specific and no longer device-agnostic.
Diffstat (limited to 'mpm')
-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; |