How to update OTP with U-Boot

Revision as of 12:52, 29 April 2020 by Registered User

This page explains how to manually update OTP with the U-Boot |fuse command.

1. The fuse command[edit source]

Warning white.png Warning
Programming fuses is an irreversible operation!

This may brick your system.
Use this command only if you are sure of what you are doing!.

The fuse command allow to update the OTP in U-Boot:

  • Sense/Program will access directly to OTP value (permanent update)
  • Read/Overidde will access to shadow cache (for temporarily update)
 STM32MP> help fuse        
 fuse - Fuse sub-system
 
 Usage:
 fuse read <bank> <word> [<cnt>] - read 1 or 'cnt' fuse words,
     starting at 'word'
 fuse sense  <bank> <word> [<cnt>] - sense 1 or 'cnt' fuse words,
     starting at 'word'
 fuse prog [-y]  <bank> <word> <hexval> [<hexval>...] - program 1 or
     several fuse words, starting at 'word' (PERMANENT)
 fuse override  <bank> <word> <hexval> [<hexval>...] - override 1 or
     several fuse words, starting at 'word'

See doc/README.fuse for details.

2. STM32MP15x support[edit source]

The STM32MP15x support is implemented in drivers/misc/stm32mp_fuse , and we support 2 bank:

2.1. STM32MP15x OTP[edit source]

<bank> = 0 provides access to the 96 STM32MP15x OTP words with the BSEC driver: arch/arm/mach-stm32mp/bsec.c .

Refer to STM32MP15 reference manuals for the OTP layout.

The OTP<index> value and lock status (0=unlocked, 1=locked) are available with word <index> = 0 to 95  :

  • for value: <word> = <index>
  • for lock status: <word> = 0x10000000 + <index>
    not shadowed, only support 'sense' and 'program'

2.1.1. Simple OTP examples[edit source]

1) read OTP value for OTP57 and 58

STM32MP> fuse sense 0 57 2
Sensing bank 0:

Word 0x00000039: 42e18000 0000e448

2) Check lock status of fuse 57 - 60 (at 0x39, 0=unlocked, 1=locked)

STM32MP>  fuse sense 0 0x10000039 4
Sensing bank 0:

Word 0x10000039: 00000001 00000001 00000001 00000000

3) Display shadow value for all OTP

STM32MP> fuse read 0 0 96
Reading bank 0:

Word 0x00000000: 00000017 00008000 00000000 00000000
Word 0x00000004: 00000000 00000000 00000000 00000000
Word 0x00000008: 00000000 00000000 00000000 00000000
Word 0x0000000c: 7cf5f0f9 00410032 33385116 34383330
Word 0x00000010: 129675aa 2931215e 7a550000 069013ec
Word 0x00000014: 5e360042 00000000 00000000 40133023
Word 0x00000018: 00000000 00000000 00000000 00000000
Word 0x0000001c: 00000000 00000000 00000000 00000000
Word 0x00000020: 00000000 00000000 00000000 00000000
Word 0x00000024: 00000000 00000000 00000000 00000000
Word 0x00000028: aa333e40 b5e90dda f15f4678 8ab41400
Word 0x0000002c: b74efe3a f0a03b1b 01e016b3 d06a79dd
Word 0x00000030: 48b96fbe 20fbd352 6732dbf4 edc395f9
Word 0x00000034: cdf15575 418fd3d0 0bb7d994 8dc929d0
Word 0x00000038: 00000000 42e18000 0000e448 12722301
Word 0x0000003c: 00000000 00000000 00000000 00000000
Word 0x00000040: 00000000 00000000 00000000 00000000
Word 0x00000044: 00000000 00000000 00000000 00000000
Word 0x00000048: 00000000 00000000 00000000 00000000
Word 0x0000004c: 00000000 00000000 00000000 00000000
Word 0x00000050: 00000000 00000000 00000000 00000000
Word 0x00000054: 00000000 00000000 00000000 00000000
Word 0x00000058: 00000000 00000000 00000000 00000000
Word 0x0000005c: 00000000 00000000 00000000 00000000

4) Override value for one OTP

STM32MP> fuse override 0 0x0000005c 1 
Overriding bank 0 word 0x0000005c with 0x00000001...
STM32MP> fuse read 0 0x0000005c      
Reading bank 0:

Word 0x0000005c: 00000001
STM32MP> fuse sense 0 0x0000005c
Sensing bank 0:

Word 0x0000005c: 00000000
STM32MP> 

2.1.2. MAC address example[edit source]

For STM32MP15_boards, the MAC address[1] is retrieved in OTP :

  • OTP_57[31:0] = MAC_ADDR[31:0]
  • OTP_58[15:0] = MAC_ADDR[47:32]

To program a MAC address on virgin OTP words above, you can use the fuse command on bank 0 to access to internal OTP and lock them:

Prerequisite: check if a MAC address isn't yet programmed in OTP

1) check OTP: their value must be equal to 0:

   STM32MP> fuse sense 0 57 2
   Sensing bank 0:
   Word 0x00000039: 00000000 00000000

2) check environment variable:

   STM32MP> env print ethaddr
   ## Error: "ethaddr" not defined

3) check lock status of fuse 57 & 58 (at 0x39, 0=unlocked, 1=locked):

   STM32MP> fuse sense 0 0x10000039 2
   Sensing bank 0:
      Word 0x10000039: 00000000 00000000

Example to set mac address "12:34:56:78:9a:bc"

1) Write OTP:

   STM32MP> fuse prog -y 0 57 0x78563412 0x0000bc9a
Warning white.png Warning
This prog command can't be executed twice because value of these 2 upper OTP words are ECC-protected.
To avoid issue these OTP must be locked when programmed.

2) Read OTP:

   STM32MP> fuse sense 0 57 2
   Sensing bank 0:
   Word 0x00000039: 78563412 0000bc9a

3) Lock OTP:

   STM32MP> fuse prog 0 0x10000039 1 1
   STM32MP> fuse sense 0 0x10000039 2
   Sensing bank 0:
      Word 0x10000039: 00000001 00000001

4) next REBOOT, in the trace:

   ### Setting environment from OTP MAC address = "12:34:56:78:9a:bc"

5) check env update:

   STM32MP> env print ethaddr
   ethaddr=12:34:56:78:9a:bc

2.2. STPMIC1 NVM[edit source]

3. References[edit source]