The STM STM32MP15 CPU provides a set of one-time programmable bits (OTPs) structured as 3072 effective bits on 96 words (from 0 to 95).
OTP words are organized in regions:
-
lower OTP (OTP0 to OTP31), for configuration options and public key
-
upper OTP (OTP32 to OTP95), for secrets (ECC protected)
The OTPs are accessed through 32-bit words.
Kernel configuration
You can manage the OTP driver support through the kernel configuration option:
-
STM32 factory-programmed memory support (
CONFIG_NVMEM_STM32_ROMEM
)
This option is enabled as built-in on the ConnectCore MP15 default kernel configuration file.
Kernel driver
The memory driver is located at:
File | Description |
---|---|
STM32 factory-programmed memory support |
Device tree bindings
The STM32MP15 OTP memory driver device tree binding are documented at
File | Description |
---|---|
STM32 BSEC device tree binding |
|
Generic NVMEM device tree bindings |
|
Generic device tree bindings |
The STM32MP15 device tree include file defines the bsec
node and inside it, a number of relevant OTP words.
bsec: efuse@5c005000 {
compatible = "st,stm32mp15-bsec";
reg = <0x5c005000 0x400>;
clocks = <&scmi_clk CK_SCMI_BSEC>;
#address-cells = <1>;
#size-cells = <1>;
part_number_otp: part_number_otp@4 {
reg = <0x4 0x1>;
};
vrefint: calib@52 {
reg = <0x52 0x2>;
};
ts_cal1: calib@5c {
reg = <0x5c 0x2>;
};
ts_cal2: calib@5e {
reg = <0x5e 0x2>;
};
ethernet_mac_address: mac@e4 {
reg = <0xe4 0x6>;
};
};
The ConnectCore MP15 defines OTP words used by the SOM, such as Digi hardware ID. It also sets the OTP words as read-only by default, to prevent accidental programming:
&bsec {
/* By default, make the OTP bits read-only */
read-only;
/* Digi hardware ID (HWID) stored in OTP59, OTP60, OTP61 */
hwid: hwid@ec {
reg = <0xec 0xc>;
};
};
OTP user space usage
The OTP words are accessible through the sysfs at /sys/bus/nvmem/devices/stm32-romem0/nvmem
.
Read the OTP bits
To dump the values of all OTP words:
# hexdump -e '"%08_ax: " 4/4 "%08x " "\n"' /sys/bus/nvmem/devices/stm32-romem0/nvmem
00000000: 00000017 00008000 a0200000 00000000
00000010: 00000000 00000000 00000000 00000000
*
00000030: 7cf5f917 00360035 32315117 32393532
00000040: 139685e7 20eb0868 7c3f0140 06be143d
00000050: 5da5003b 00000000 00000000 3f992fe9
00000060: 00000000 00000000 00000000 00000000
Certain OTP words, such as security keys, cannot be read so they show as 00000000 .
|
To dump only a certain OTP word use the dd
command, skip the offset of the word, and pipe the result to hexdump
.
For instance, to dump OTP word 12, use:
# dd status=none if=/sys/bus/nvmem/devices/stm32-romem0/nvmem of=/dev/stdout bs=4 count=1 skip=12 | hexdump -v -e '4/4 "%08x " "\n"'
7cf5f917
Write the OTP bits
OTP bits can be blown just once. Programming them is an irreversible operation. OTP bits on ECC-protected regions should only be written once. Writing a second time may lead to errors. |
By default, OTP bits access is configured as read-only on Linux device tree. To enable write permissions, add the following to your Linux device tree:
&bsec {
/delete-property/read-only;
};
Recompile the Linux device tree and deploy it to your device.
OTP bits access is done in 32-bit words.
To write a 32-bit value to a specific word, use printf
and pipe the output to dd
:
# printf <value> | dd of=/sys/bus/nvmem/devices/stm32-romem0/nvmem bs=4 count=1 seek=<offset> conv=notrunc
where:
-
<value>
is the 32-bit value to write. Specify the value in little-endian byte order. -
bs=4
sets the block size in 4 bytes (a full 32-bit word). -
count=1
sets the blocks (words) to write (1 = 4 bytes). -
seek=<offset>
sets the offset (in words) where to write. -
conv=notrunc
avoids truncating the output.
For example, to write the word 0x12345678
to word N, swap the bytes to present them in little-endian to the printf
command:
# printf '\x78\x56\x34\x12' | dd of=/sys/bus/nvmem/devices/stm32-romem0/nvmem bs=4 count=1 seek=N conv=notrunc
Programming of the OTP bits happens without user confirmation. Make sure you double check the value and the word offset you want to program before running a command like this. |