The NXP {cpu-family} CPU provides a set of one-time programmable bits (eFuses) structured as 16 banks. Each bank is composed of eight 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 6 Plus 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 {cpu-family} OTP memory driver device tree binding is documented at Documentation/devicetree/bindings/nvmem/imx-ocotp.txt
.
ocotp: ocotp@21bc000 {
compatible = "fsl,imx6q-ocotp", "syscon";
reg = <0x021bc000 0x4000>;
clocks = <&clks IMX6QDL_CLK_IIM>;
};
The ConnectCore 6 Plus 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: 20220003 e31698d7 0f0a89d4 202200c0
00000010: 00600302 00000000 00000000 00000000
00000020: 00000080 00000040 0000009f 00000000
00000030: 00000000 80000000 5654de69 00000000
00000040: badabada badabada badabada badabada
*
00000060: 00000000 00000000 00000000 00000000
*
00000080: 00000000 00000000 b0208705 3f100450
00000090: 00000000 00000000 00000003 00000000
000000a0: 00000000 00000000 00000000 00000000
*
00000100: 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" * 8) + "Word"\$
For example, for Bank 4 Word 3, the offset is 4 * 8 + 3 = 35.
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=35 | hexdump -v -e '4/4 "%08x " "\n"'
00000540
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" * 8) + "Word"\$
For example, for Bank 4 Word 3, the offset is 4 * 8 + 3 = 35.
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=35 conv=notrunc