[1/2] warp7: usb: Introduce a get method for serial number

Message ID 1520942427-7366-2-git-send-email-bryan.odonoghue@linaro.org
State New
Headers show
Series
  • NXP WaARP7 set serial# from OTP fuses for USB iSerial
Related show

Commit Message

Bryan O'Donoghue March 13, 2018, noon
We want to be able to set the USB device descriptor number iSerial number
or indeed a disk-label unique identifier based on a chip-specific piece of
data for the purposes of differentiating between WaRP7 boards via lsusb
when connected to a host machine.

In order to do this we want to have a serial number encoded in hardware,
which will persist across bootloader, filesystem and config file changes.

This patch utilises OCOTP_TESTER0 AND OCOTP_TESTER1 respectively for this
purpose. OCOTP_TESTER is a unique identifier for each chip representing

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>
Reviewed-by: Rui Miguel Silva <rui.silva@linaro.org>
Reviewed-by: Ryan Harkin <ryan.harkin@linaro.org>
---
 board/warp7/warp7.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

Comments

Fabio Estevam March 13, 2018, 1:25 p.m. | #1
Hi Bryan,

On Tue, Mar 13, 2018 at 9:00 AM, Bryan O'Donoghue
<bryan.odonoghue@linaro.org> wrote:

> +static int warp7_get_serialid(u64 *id)

Maybe you could turn place this function in a common location as it
may be useful for others.

> +{
> +       u32 val;
> +       int ret;
> +
> +       if (!id)
> +               return -EINVAL;
> +
> +       /* Read first word */
> +       ret = fuse_read(WARP7_USB_SERIALID_BANK, WARP7_USB_SERIALID_MSWORD, &val);
> +       if (ret)
> +               goto done;

Better just do 'return ret' instead of jumping to the 'done' label.
Bryan O'Donoghue March 13, 2018, 2:17 p.m. | #2
On 13/03/18 13:25, Fabio Estevam wrote:
>> +static int warp7_get_serialid(u64 *id)
> Maybe you could turn place this function in a common location as it
> may be useful for others.
> 

Ah, looking for a place to stick this as shared code I've found 
something which already does what this patch does

arch/arm/mach-imx/mx7/soc.c::void get_board_serial(struct tag_serialnr 
*serialnr)

commit c5752f73a53a ("imx: imx7d: Add SoC system support")

Patch

diff --git a/board/warp7/warp7.c b/board/warp7/warp7.c
index d422d63..2cec448 100644
--- a/board/warp7/warp7.c
+++ b/board/warp7/warp7.c
@@ -23,6 +23,7 @@ 
 #include <power/pmic.h>
 #include <power/pfuze3000_pmic.h>
 #include "../freescale/common/pfuze.h"
+#include <fuse.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -90,6 +91,58 @@  static struct fsl_esdhc_cfg usdhc_cfg[1] = {
 	{USDHC3_BASE_ADDR},
 };
 
+/*
+ * 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
+ */
+#define WARP7_USB_SERIALID_BANK 0
+#define WARP7_USB_SERIALID_MSWORD 1
+#define WARP7_USB_SERIALID_LSWORD 2
+
+static int warp7_get_serialid(u64 *id)
+{
+	u32 val;
+	int ret;
+
+	if (!id)
+		return -EINVAL;
+
+	/* Read first word */
+	ret = fuse_read(WARP7_USB_SERIALID_BANK, WARP7_USB_SERIALID_MSWORD, &val);
+	if (ret)
+		goto done;
+
+	*id = val;
+	*id <<= 32;
+
+	/* Read second word */
+	ret = fuse_read(WARP7_USB_SERIALID_BANK, WARP7_USB_SERIALID_LSWORD, &val);
+	if (ret)
+		goto done;
+
+	*id |= val;
+
+done:
+	return ret;
+}
+
 int board_mmc_getcd(struct mmc *mmc)
 {
 		/* Assume uSDHC3 emmc is always present */