[U-Boot] [PATCH v2 0/3] NXP WaARP7 set serial# from OTP fuses for USB iSerial

V2: - Fix compilation path for CONFIG_SERIAL_TAG Currently this is broken for imx7
- Add description of tester registers to arch/arm/mach-imx/mx7/soc.c
- Utilise existing get_board_serial() instead of my previous patch ("warp7: usb: Introduce a get method for serial number")
V1: Greetings.
These two patches add support for automatic setting of the serial# environment variable based on OTP fuse settings. Once the serial# field is set then subsequent USB gadget mode instances of WaARP7 will export the serial number based on the OTP fuse settings.
This feature gives a handy output like this:
usb 1-1.1.1: new high-speed USB device number 17 using xhci_hcd usb 1-1.1.1: New USB device found, idVendor=0525, idProduct=a4a5 usb 1-1.1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3 usb 1-1.1.1: Product: USB download gadget usb 1-1.1.1: Manufacturer: FSL usb 1-1.1.1: SerialNumber: WaRP7-0xf42400d3000001d4
The 64 bit value post-fixed to the WaARP7 string is based on OTP fuses which provide a unique serial number for each NXP i.MX7 SoC.
We make use of this feature when discerning a unique identifier for WaARP7 boards in our automated LAVA testing environment, hopefully its useful and acceptable to others.
Bryan O'Donoghue (3): imx: mx7: Fix CONFIG_SERIAL_TAG compilation imx: mx7: Add comment to describe OTP TESTER registers warp7: Set u-boot serial# based on OTP value
arch/arm/mach-imx/mx7/soc.c | 22 ++++++++++++++++++++++ board/warp7/warp7.c | 14 ++++++++++++++ include/configs/warp7.h | 3 +++ 3 files changed, 39 insertions(+)

Currently when we define CONFIG_SERIAL_TAG we will barf with a failure to define "struct tag_serialnr".
This structure is defined in <asm/setup.h>, this patch includes <asm/setup.h> to fix.
Signed-off-by: Bryan O'Donoghue bryan.odonoghue@linaro.org Cc: Fabio Estevam fabio.estevam@nxp.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de --- arch/arm/mach-imx/mx7/soc.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm/mach-imx/mx7/soc.c b/arch/arm/mach-imx/mx7/soc.c index d349676..1602585 100644 --- a/arch/arm/mach-imx/mx7/soc.c +++ b/arch/arm/mach-imx/mx7/soc.c @@ -18,6 +18,7 @@ #include <dm.h> #include <imx_thermal.h> #include <fsl_sec.h> +#include <asm/setup.h>
#if defined(CONFIG_IMX_THERMAL) static const struct imx_thermal_plat imx7_thermal_plat = {

On Tue, Mar 13, 2018 at 12:48 PM, Bryan O'Donoghue bryan.odonoghue@linaro.org wrote:
Currently when we define CONFIG_SERIAL_TAG we will barf with a failure to define "struct tag_serialnr".
This structure is defined in <asm/setup.h>, this patch includes <asm/setup.h> to fix.
Signed-off-by: Bryan O'Donoghue bryan.odonoghue@linaro.org Cc: Fabio Estevam fabio.estevam@nxp.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de
Reviewed-by: Fabio Estevam fabio.estevam@nxp.com

The tester registers provide a unique chip-level identifier which get_board_serial() returns in a "struct tag_serialnr".
This patch documents the properties of the registers; in summary.
31:0 OCOTP_TESTER0 (most significant) - FSL-wide unique, encoded LOT ID STD II/SJC CHALLENGE/ Unique ID
OCOTP_TESTER1 (least significant) 31:24 - The X-coordinate of the die location on the wafer/SJC CHALLENGE/ Unique ID 23:16 - The Y-coordinate of the die location on the wafer/SJC CHALLENGE/ Unique ID 15:11 - The wafer number of the wafer on which the device was fabricated/SJC CHALLENGE/ Unique ID 10:0 - FSL-wide unique, encoded LOT ID STD II/SJC CHALLENGE/ Unique ID
The 64 bits of data generate a unique serial number per-chip.
Signed-off-by: Bryan O'Donoghue bryan.odonoghue@linaro.org Cc: Fabio Estevam fabio.estevam@nxp.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de --- arch/arm/mach-imx/mx7/soc.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
diff --git a/arch/arm/mach-imx/mx7/soc.c b/arch/arm/mach-imx/mx7/soc.c index 1602585..fb92a26 100644 --- a/arch/arm/mach-imx/mx7/soc.c +++ b/arch/arm/mach-imx/mx7/soc.c @@ -202,6 +202,27 @@ int arch_misc_init(void) #endif
#ifdef CONFIG_SERIAL_TAG +/* + * OCOTP_TESTER + * i.MX 7Solo Applications Processor Reference Manual, Rev. 0.1, 08/2016 + * OCOTP_TESTER describes a unique ID based on silicon wafer + * and die X/Y position + * + * OCOTOP_TESTER offset 0x410 + * 31:0 fuse 0 + * FSL-wide unique, encoded LOT ID STD II/SJC CHALLENGE/ Unique ID + * + * OCOTP_TESTER1 offset 0x420 + * 31:24 fuse 1 + * The X-coordinate of the die location on the wafer/SJC CHALLENGE/ Unique ID + * 23:16 fuse 1 + * The Y-coordinate of the die location on the wafer/SJC CHALLENGE/ Unique ID + * 15:11 fuse 1 + * The wafer number of the wafer on which the device was fabricated/SJC + * CHALLENGE/ Unique ID + * 10:0 fuse 1 + * FSL-wide unique, encoded LOT ID STD II/SJC CHALLENGE/ Unique ID + */ void get_board_serial(struct tag_serialnr *serialnr) { struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;

On Tue, Mar 13, 2018 at 12:48 PM, Bryan O'Donoghue bryan.odonoghue@linaro.org wrote:
The tester registers provide a unique chip-level identifier which get_board_serial() returns in a "struct tag_serialnr".
This patch documents the properties of the registers; in summary.
31:0 OCOTP_TESTER0 (most significant)
- FSL-wide unique, encoded LOT ID STD II/SJC CHALLENGE/ Unique ID
OCOTP_TESTER1 (least significant) 31:24
- The X-coordinate of the die location on the wafer/SJC CHALLENGE/ Unique ID
23:16
- The Y-coordinate of the die location on the wafer/SJC CHALLENGE/ Unique ID
15:11
- The wafer number of the wafer on which the device was fabricated/SJC CHALLENGE/ Unique ID
10:0
- FSL-wide unique, encoded LOT ID STD II/SJC CHALLENGE/ Unique ID
The 64 bits of data generate a unique serial number per-chip.
Signed-off-by: Bryan O'Donoghue bryan.odonoghue@linaro.org Cc: Fabio Estevam fabio.estevam@nxp.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de
Reviewed-by: Fabio Estevam fabio.estevam@nxp.com

u-boot has a standard "serial#" environment variable that is suitable for storing the iSerial number we will supply via the USB device descriptor. serial# is automatically picked up by the disk subsystem in u-boot - thus providing a handy unique identifier in /dev/disk/by-id as detailed below.
Storing the hardware serial identifier in serial# means we can change the serial# if we want before USB enumeration - thus making iSerial automatic via OTP but overridable if necessary.
This patch reads the defined OTP fuse and sets environment variable "serial#" to the value read.
With this patch in place the USB mass storage device will appear in /dev/disk/by-id with a unique name based on the OTP value. For example
/dev/disk/by-id/usb-Linux_UMS_disk_0_WaRP7-0xf42400d3000001d4-0:0
Signed-off-by: Bryan O'Donoghue bryan.odonoghue@linaro.org Cc: Fabio Estevam fabio.estevam@nxp.com Cc: Rui Miguel Silva rui.silva@linaro.org Cc: Ryan Harkin ryan.harkin@linaro.org --- board/warp7/warp7.c | 14 ++++++++++++++ include/configs/warp7.h | 3 +++ 2 files changed, 17 insertions(+)
diff --git a/board/warp7/warp7.c b/board/warp7/warp7.c index d422d63..327f656 100644 --- a/board/warp7/warp7.c +++ b/board/warp7/warp7.c @@ -23,6 +23,8 @@ #include <power/pmic.h> #include <power/pfuze3000_pmic.h> #include "../freescale/common/pfuze.h" +#include <asm/setup.h> +#include <asm/bootm.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -186,6 +188,10 @@ int board_usb_phy_mode(int port) int board_late_init(void) { struct wdog_regs *wdog = (struct wdog_regs *)WDOG1_BASE_ADDR; +#ifdef CONFIG_SERIAL_TAG + struct tag_serialnr serialnr; + char serial_string[0x20]; +#endif
imx_iomux_v3_setup_multiple_pads(wdog_pads, ARRAY_SIZE(wdog_pads));
@@ -197,5 +203,13 @@ int board_late_init(void) */ clrsetbits_le16(&wdog->wcr, 0, 0x10);
+#ifdef CONFIG_SERIAL_TAG + /* Set serial# standard environment variable based on OTP settings */ + get_board_serial(&serialnr); + snprintf(serial_string, sizeof(serial_string), "WaRP7-0x%08x%08x", + serialnr.low, serialnr.high); + env_set("serial#", serial_string); +#endif + return 0; } diff --git a/include/configs/warp7.h b/include/configs/warp7.h index fe96988..0c3b605 100644 --- a/include/configs/warp7.h +++ b/include/configs/warp7.h @@ -24,6 +24,9 @@ #define CONFIG_SYS_FSL_ESDHC_HAS_DDR_MODE #define CONFIG_SYS_MMC_IMG_LOAD_PART 1
+/* Switch on SERIAL_TAG */ +#define CONFIG_SERIAL_TAG + #define CONFIG_DFU_ENV_SETTINGS \ "dfu_alt_info=boot raw 0x2 0x400 mmcpart 1\0" \

On Tue, Mar 13, 2018 at 12:48 PM, Bryan O'Donoghue bryan.odonoghue@linaro.org wrote:
u-boot has a standard "serial#" environment variable that is suitable for storing the iSerial number we will supply via the USB device descriptor. serial# is automatically picked up by the disk subsystem in u-boot - thus providing a handy unique identifier in /dev/disk/by-id as detailed below.
Storing the hardware serial identifier in serial# means we can change the serial# if we want before USB enumeration - thus making iSerial automatic via OTP but overridable if necessary.
This patch reads the defined OTP fuse and sets environment variable "serial#" to the value read.
With this patch in place the USB mass storage device will appear in /dev/disk/by-id with a unique name based on the OTP value. For example
/dev/disk/by-id/usb-Linux_UMS_disk_0_WaRP7-0xf42400d3000001d4-0:0
Signed-off-by: Bryan O'Donoghue bryan.odonoghue@linaro.org Cc: Fabio Estevam fabio.estevam@nxp.com Cc: Rui Miguel Silva rui.silva@linaro.org Cc: Ryan Harkin ryan.harkin@linaro.org
Reviewed-by: Fabio Estevam fabio.estevam@nxp.com
participants (2)
-
Bryan O'Donoghue
-
Fabio Estevam