The NXP i.MX8M Nano CPU provides a set of one-time programmable bits (eFuses) structured as 15 banks. Each bank is composed of four words of 32 bits each.
Kernel configuration
You can manage the OTP driver support through the kernel configuration option:
-
NXP NVMEM On-Chip OTP Memory support (
CONFIG_NVMEM_IMX_OCOTP
)
This option is enabled as built-in on the ConnectCore 8M Nano default kernel configuration file.
Kernel driver
The OTP memory driver is located at:
File | Description |
---|---|
i.MX 6/7/8 On-Chip OTP Controller support |
Device tree bindings
The i.MX8M Nano OTP memory driver device tree binding is documented at Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml
.
ocotp: efuse@30350000 {
compatible = "fsl,imx8mn-ocotp", "fsl,imx8mm-ocotp", "syscon", "simple-mfd";
reg = <0x30350000 0x10000>;
clocks = <&clk IMX8MN_CLK_OCOTP_ROOT>;
/* For nvmem subnodes */
#address-cells = <1>;
#size-cells = <1>;
imx8mn_uid: unique-id@410 {
reg = <0x4 0x8>;
};
cpu_speed_grade: speed-grade@10 {
reg = <0x10 4>;
};
fec_mac_address: mac-address@90 {
reg = <0x90 6>;
};
imx8mn_soc: imx8mn-soc {
compatible = "fsl,imx8mn-soc";
nvmem-cells = <&imx8mn_uid>;
nvmem-cell-names = "soc_unique_id";
};
};
The ConnectCore 8M Nano device tree sets read-only access to the OTP bits to prevent accidental programming of the e-fuses.
&ocotp {
/* By default, make the OTP bits read-only */
read-only;
};
OTP user space usage
The OTP words are accessible through the sysfs at /sys/bus/nvmem/devices/imx-ocotp0/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/imx-ocotp0/nvmem
00000000: feafa9eb 50d00200 24226998 00000000
00000010: 20000800 00020000 0000007f 08000000
00000020: 00000000 00000000 00000000 00000000
00000030: 00000000 00000000 00000000 013c7b3a
00000040: badabada badabada badabada badabada
*
00000060: 00000000 00000000 00000000 00000000
*
00000090: 14100009 118e0b01 0007b848 00000000
000000a0: badabada badabada badabada badabada
*
000000c0: 00000000 00000000 00000000 00000000
*
000000f0: badabada badabada badabada 00000000
00000100: 00000000 00000000 00000000 00000000
*
00000130: badabada badabada badabada badabada
00000140: 55002001 00028840 0003f000 0000eddc
00000150: a8c1302b 0000ede8 a881300b 00025c54
00000160: 52801e00 00000000 00000000 00000000
00000170: 00000000 00000000 00000000 00000000
*
000003e0: 00000000 00000000 00000001 07c31a01
000003f0: badabada badabada badabada badabada
The values showing badabada correspond to OTP words that cannot be read, such as encryption keys.
|
To dump only a certain OTP word, do not use the -s
parameter of the hexdump
command.
Instead, use the dd
command and pipe the result to hexdump
.
To calculate the offset of the word, use the formula:
\$"Offset" = ("Bank" * 4) + "Word"\$
For example, for Bank 9 Word 1, the offset is 9 * 4 + 1 = 37.
Use dd
with a block size (bs) of 4 bytes, a count of 1 word, and skip the calculated offset:
# dd status=none if=/sys/bus/nvmem/devices/imx-ocotp0/nvmem of=/dev/stdout bs=4 count=1 skip=37 | hexdump -v -e '4/4 "%08x " "\n"'
118e0b01
Write the OTP bits
OTP bits can be blown just once. Programming them is an irreversible operation. |
By default, OTP bit access is configured as read-only. To enable write permissions, add the following to your device tree:
&ocotp {
/delete-property/read-only;
};
Recompile the device tree and deploy it to your device.
OTP bit 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/imx-ocotp0/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 in 1 (4 bytes). -
seek=<offset>
sets the offset (in words) where to write. -
conv=notrunc
avoids truncating the output.
To calculate the offset of the word, use the formula:
\$"Offset" = ("Bank" * 4) + "Word"\$
For example, for Bank 9 Word 1, the offset is 9 * 4 + 1 = 37.
To write the word 0x12345678
to that offset, swap the bytes to present them in little-endian to the printf
command:
# printf '\x78\x56\x34\x12' | dd of=/sys/bus/nvmem/devices/imx-ocotp0/nvmem bs=4 count=1 seek=37 conv=notrunc