Registered User mNo edit summary |
Registered User mNo edit summary Tag: 2017 source edit |
||
(95 intermediate revisions by 8 users not shown) | |||
Line 1: | Line 1: | ||
<noinclude>{{ApplicableFor | <noinclude>{{ApplicableFor | ||
|MPUs list=STM32MP13x, STM32MP15x | |MPUs list=STM32MP13x, STM32MP15x, STM32MP21x, STM32MP23x, STM32MP25x | ||
|MPUs checklist=STM32MP13x,STM32MP15x | |MPUs checklist=STM32MP13x, STM32MP15x, STM32MP21x, STM32MP23x, STM32MP25x | ||
}}</noinclude> | }} | ||
This article introduces how NVMEM Linux<sup>®</sup> framework manages | </noinclude> | ||
{{TrustedDomainApplicability | TDflavor = M33-TD| applicable = no}} | |||
This article introduces how the NVMEM Linux<sup>®</sup> framework manages '''Non Volatile Memory''' data and how to read/write from/to it. | |||
==Framework purpose== | ==Framework purpose== | ||
The NVMEM Linux<sup>®</sup> framework provides a generic interface for | The NVMEM Linux<sup>®</sup> framework provides a generic interface for '''non-volatile memory data''' devices such as: | ||
* OTP (one-time programmable) fuses | * '''OTP''' (one-time programmable) fuses, for example [[BSEC internal peripheral|BSEC]] OTP | ||
* EEPROM | * '''EEPROM''' | ||
It offers kernel space and user space interfaces to read | * '''Battery backed memory''', for example [[TAMP internal peripheral|TAMP]] backup registers | ||
It offers kernel space and user space interfaces to read/write data such as analog calibration data or MAC address. | |||
==System overview== | ==System overview== | ||
{{ ImageMap|Image:NVMEM_overview.png | {{ ImageMap|Image:NVMEM_overview.png {{!}} 800px {{!}} center{{!}} | ||
rect | rect 434 93 466 110 [[NVMEM_overview#API description|NVMEM sysfs interface]] | ||
rect | rect 500 152 588 171 [[NVMEM_overview#API description|NVMEM consumers interface]] | ||
rect | rect 345 427 422 451 [[BSEC internal peripheral]] | ||
rect | rect 476 426 580 453 [[TAMP_internal_peripheral]] | ||
rect 230 | rect 344 346 422 373 [[OP-TEE OTP overview|BSEC PTA ]] | ||
rect | rect 230 342 276 361 [[STM32 MPU OP-TEE overview|OP-TEE]] | ||
rect | rect 344 293 422 319 [[OP-TEE_concepts_overview#TEE_Linux_driver|OP-TEE linux driver]] | ||
rect 374 267 422 286 [[OP-TEE_concepts_overview#TEE_Client_API|TEE Client API]] | |||
}} | }} | ||
===Component description=== | ===Component description=== | ||
* '''NVMEM user''' (user space) | * '''NVMEM user''' (user space) | ||
The user can use the NVMEM sysfs interface | The user can use the NVMEM sysfs interface from a user terminal or a custom application to read/write data from/to NVMEM devices, and from user space. | ||
* '''NVMEM user''' (kernel space) | * '''NVMEM user''' (kernel space) | ||
The 'foo_driver' could be any driver in kernel space that uses the NVMEM API to read/write data from/to NVMEM devices (such as the analog calibration data used by an ADC driver). | |||
* '''NVMEM framework''' (kernel space) | * '''NVMEM framework''' (kernel space) | ||
The NVMEM core provides sysfs interface and NVMEM API. They can be used to implement NVMEM user and NVMEM controller drivers. | The NVMEM core provides sysfs interface and NVMEM API. They can be used to implement NVMEM user and NVMEM controller drivers. | ||
* '''NVMEM drivers''' (kernel space) | * '''NVMEM drivers''' (kernel space) : | ||
** STM32 ROMEM Linux<sup>®</sup> driver that exposes BSEC OTP data to the core. | |||
** STM32 TAMP NVRAM Linux<sup>®</sup>driver that exposes non secure backup registers to the core. | |||
* '''TEE framework''' (kernel space) | * '''TEE framework''' (kernel space) | ||
The TEE framework provides [[OP- | The TEE framework provides [[OP-TEE_concepts_overview#TEE_Client_API|TEE client API]] to communicate with secure services, as the services provided by the OP-TEE Linux<sup>®</sup> driver. | ||
* ''' OP-TEE''' (Secure) | * ''' OP-TEE''' (Secure) | ||
The [[OP-TEE overview|'''OP-TEE secure OS''']] is running on the Cortex-A in [[Security_overview|secure mode]] and exposes secure service with | The [[STM32 MPU OP-TEE overview|'''OP-TEE secure OS''']] is running on the Cortex-A in [[Security_overview|secure mode]] and exposes secure service with interfaces such as [[OP-TEE OTP overview|BSEC PTA ]] and [[OP-TEE OTP overview|TA STM32MP NVMEM]]. | ||
* '''NVMEM hardware''' | * '''NVMEM hardware''' | ||
NVMEM | NVMEM controllers such as the [[BSEC internal peripheral]] for OTP or [[TAMP internal peripheral]] for Backup Registers. | ||
===API description=== | ===API description=== | ||
The NVMEM kernel documentation | The NVMEM kernel documentation describes in {{DocSource | domain=Linux kernel | path=driver-api/nvmem.html}}: | ||
* Kernel space API for NVMEM '''providers''' | * Kernel space API | ||
* | ** for NVMEM '''providers''' ({{CodeSource | Linux kernel | include/linux/nvmem-provider.h}}) | ||
** for NVMEM '''consumers''' ({{CodeSource | Linux kernel | include/linux/nvmem-consumer.h}}), | |||
* User space binary interface (sysfs) for {{DocSource | domain=Linux kernel | path=admin-guide/abi-stable.html#abi-sys-bus-nvmem-devices-nvmem|text=sysfs-bus-nvmem}} documentation. | |||
==Configuration== | ==Configuration== | ||
===Kernel configuration=== | ===Kernel configuration=== | ||
Activate NVMEM framework in the kernel configuration through the Linux<sup>®</sup> menuconfig tool | Activate NVMEM framework in the kernel configuration through the Linux<sup>®</sup> menuconfig tool (see [[Menuconfig or how to configure kernel | Menuconfig or how to configure kernel]]) with CONFIG_NVMEM = y: | ||
Device Drivers ---> | Device Drivers ---> | ||
[*] NVMEM Support ---> | [*] NVMEM Support ---> | ||
Line 53: | Line 62: | ||
The NVMEM data device tree bindings describe: | The NVMEM data device tree bindings describe: | ||
* The location of non-volatile memory data | * The location of non-volatile memory data | ||
* The NVMEM data providers | * The NVMEM data providers ({{CodeSource | Linux kernel | Documentation/devicetree/bindings/nvmem/nvmem.yaml}}): BSEC and TAMP | ||
* The NVMEM data consumers | * The NVMEM data consumers ({{CodeSource | Linux kernel | Documentation/devicetree/bindings/nvmem/nvmem-consumer.yaml}}) | ||
The | The [[BSEC internal peripheral]] device tree bindings are described in the [[BSEC device tree configuration]] article. | ||
The [[TAMP internal peripheral]] device tree bindings are described in the [[TAMP device tree configuration]] article. | |||
==How to use the framework== | ==How to use the framework== | ||
===How to use NVMEM with sysfs interface=== | ===How to use NVMEM with sysfs interface=== | ||
====How to list NVMEM devices==== | ====How to list NVMEM devices==== | ||
The available NVMEM devices can be listed in sysfs directory {{Highlight|/sys/bus/nvmem/devices}} | The available NVMEM devices can be listed in sysfs directory {{Highlight|/sys/bus/nvmem/devices}}. | ||
Example | Example of '''listing''' nvmem devices: | ||
{{Board$}} ls /sys/bus/nvmem/devices/ | * BSEC is '''stm32-romem0''' | ||
* TAMP Backup Registers is '''stm32-tamp-nvram0''' | |||
{{Board$}}ls /sys/bus/nvmem/devices/ | |||
stm32-romem0 | stm32-romem0 | ||
stm32-tamp-nvram0 | |||
====How to read | ====How to read OTP areas using NVMEM==== | ||
The user space can read/write the raw NVMEM file located at {{Highlight|/sys/bus/nvmem/devices/*/nvmem}}. | |||
For BSEC, the | For BSEC, the NVMEM is the '''stm32-romem0''' device. The content of '''non-secure OTP areas''' can be read but the '''secured OTP areas''' are masked, and their values replaced by 0. | ||
On {{MicroprocessorDevice | device=1}}, only lower OTPs (OTP 0 to 31) are accessible by the non-secure world by default. The upper OTP data being restricted to security. If the user needs more than the lower OTP data, this can be managed by an exception described in [[BSEC device tree configuration|OP-TEE device tree]]. | |||
On {{MicroprocessorDevice | device=2}}, lower and middle OTPs (OTP 0 to 255) are accessible by the non-secure world. The device tree on {{MicroprocessorDevice | device=2}} does not support exception to give read-access to upper OTP (see [[BSEC device tree configuration#BSEC_node_append|OP-TEE device tree]] page for details). | |||
* Example to ''' | * Example of '''reading''' all nvmem data on stm32-romem0 devices | ||
{{Board$}} hexdump -C -v /sys/bus/nvmem/devices/stm32-romem0/nvmem | {{Board$}}dd if=/sys/bus/nvmem/devices/stm32-romem0/nvmem of=/tmp/file | ||
* Example of '''displaying''' all nvmem data | |||
{{Board$}}hexdump -C -v /sys/bus/nvmem/devices/stm32-romem0/nvmem | |||
{{Info|A dedicated page describes the OTP area mapping for [[STM32MP15_OTP_mapping|STM32MP13]], [[STM32MP15_OTP_mapping|STM32MP15]], [[STM32MP21_OTP_mapping|STM32MP21]] and [[STM32MP23-25 OTP mapping|STM32MP23-25]].}} | |||
====How to write BSEC OTP data using NVMEM==== | |||
{{Warning|The below examples show how to write data to an NVMEM device. This may cause unrecoverable damage to the STM32 device (for example when writing to an OTP area)}} | |||
{{Info| Note that lower BSEC OTP areas are using 2:1 redundancy, so they can be written bit per bit, whereas upper BSEC OTP areas only support one time 32-bit programming and are automatically locked by the driver.}} | |||
The BSEC OTP areas can be written by 32-bit word starting at OTP {{highlight|N}}, as follows: | |||
# {{highlight|'''write''' OTP '''N'''}} word by word | |||
{{Board$}}dd if={{highlightParam|/tmp/file}} of=/sys/bus/nvmem/devices/stm32-romem0/nvmem bs=4 seek={{highlight|N}} | |||
or | |||
# {{highlight|'''write''' OTP '''N'''}}, all the file in one request | |||
{{Board$}}dd if={{highlightParam|/tmp/file}} of=/sys/bus/nvmem/devices/stm32-romem0/nvmem seek={{highlight|4*N}} oflag=seek_bytes | |||
With a file {{highlightParam|/tmp/file}} containing the OTP data to write, its size is 32-bit word aligned, for example: | |||
# Create a 4 bytes length file filled with ones, e.g. 0xffffffff) | |||
{{Board$}}dd if=/dev/zero count=1 bs=4 | tr '\000' '\377' > file | |||
# Create a 4 bytes length file, here 0x00000001 to update one OTP | |||
{{Board$}}echo -n -e '\x01\x00\x00\x00' > {{highlightParam|/tmp/file}} | |||
# Create a 8 bytes length file, here 0x67452301 0xEFCDAB89 to update two OTPs | |||
{{Board$}}echo -n -e '\x01\x23\x45\x67\x89\xAB\xCD\xEF' > {{highlightParam|/tmp/file}} | |||
A lower OTP area can be written several times for a bit per bit update if it is not locked. | |||
An upper OTP area can be written only if it is allowed in [[BSEC_device_tree_configuration#BSEC_node_append|secure world device tree]], and only once. When the upper OTP is written, it is permanent locked at the end of the NVMEM request to an avoid ECC issue on the second update. For the first example with bs = 4, this lock is performed after each OTP update, while for the second example with oflag = seek_bytes, it is done when all the OTP data in the input file are updated. | |||
{{Info|When a new OTP value has been written using this SYSFS interface, it may be necessary to reboot the board before reading it back. The OTP value cannot be read directly after a write because the OTP value is read in a shadow area that is not directly in the OTP area.}} | |||
Below a compete example of writing the upper OTP 60: | |||
{{Board$}}echo -n -e {{highlight|'\x01\x23\x45\x67'}} > /tmp/file | |||
hexdump -C /tmp/file | |||
00000000 {{highlight|01 23 45 67}} |.#Eg| | |||
00000004 | |||
{{Board$}}dd if=/tmp/file of=/sys/bus/nvmem/devices/stm32-romem0/nvmem bs=4 seek={{highlightParam|60}} | |||
{{Board$}}reboot | |||
<< >> | |||
{{Board$}}hexdump -C -v /sys/bus/nvmem/devices/stm32-romem0/nvmem | |||
.... | |||
{{highlightParam|000000f0}} {{highlight|01 23 45 67}} 00 00 00 00 00 00 00 00 00 00 00 00 |.#Eg............| | |||
.... | |||
The associated output in [[STM32CubeProgrammer#How_to_fuse_STM32MP15x_OTP|STM32CubeProgrammer]] is: <br> | |||
OTP REGISTERS: | |||
--------------------------------------------------------------------------- | |||
ID | value | status | |||
--------------------------------------------------------------------------- | |||
... | |||
060 | 0x67452301 | 0x40000000 | |||
|_[30] Permanent write lock | |||
or in [[How_to_update_OTP_with_U-Boot|U-Boot]] | |||
{{U-Boot$}}fuse read 0 0 96 | |||
... | |||
Word 0x0000003c: 67452301 00000000 00000000 00000000 | |||
... | |||
===How to use NVMEM with kernel space API=== | |||
== | Here is an example of the kernel space API.<br> | ||
To describe the memory area, the device tree must include a node with the properties '''nvmem-cells''' and '''nvmem-cell-names'''. An example for the backup register can be found in [[TAMP_device_tree_configuration#How_to_use_TAMP_Backup_Registers | TAMP device tree configuration]]. | |||
<pre> | |||
&my_device_tree_node { | |||
nvmem-cells = <&phandle_cell>; | |||
nvmem-cell-names = "nvmem_cell_name"; | |||
} | |||
</pre> | |||
Invoke '''nvmem_cell_get''' to get your nvmem_cell within your driver. The functions '''nvmem_cell_read''' and '''nvmem_cell_write''' allows to read or write the memory area. | |||
<pre> | |||
struct nvmem_cell *my_cell = nvmem_cell_get(my_driver_dev, "nvmem_cell_name"); | |||
if (IS_ERR_OR_NULL(my_cell)) { | |||
dev_err(my_driver_dev, "No cell for my device %ld\n", PTR_ERR(my_cell)); | |||
return PTR_ERR(my_cell); | |||
} | |||
//Read the cell | |||
int my_cell_length = 0; | |||
int* my_cell_content = nvmem_cell_read(my_cell, &my_cell_length); | |||
*my_cell_content += 1; | |||
//Update the cell | |||
nvmem_cell_write(my_cell, &my_cell_length,sizeof(int)); | |||
... | |||
</pre> | |||
==How to trace | ==How to trace the framework== | ||
[[Ftrace]] can be used to trace the NVMEM framework: | [[Ftrace]] can be used to trace the NVMEM framework: | ||
{{Board$}} cd /sys/kernel/debug/tracing | {{Board$}}cd /sys/kernel/debug/tracing | ||
{{Board$}} cat available_filter_functions | grep nvmem # Show available filter functions | {{Board$}}cat available_filter_functions | grep nvmem # Show available filter functions | ||
rtc_nvmem_register | rtc_nvmem_register | ||
rtc_nvmem_unregister | rtc_nvmem_unregister | ||
Line 99: | Line 196: | ||
... | ... | ||
Enable the kernel function tracer, then start using nvmem and display the result: | Enable the kernel function tracer, then start using nvmem and display the result: | ||
{{Board$}} echo function > current_tracer | {{Board$}}echo function > current_tracer | ||
{{Board$}} echo "*nvmem*" > set_ftrace_filter # Trace all nvmem filter functions | {{Board$}}echo "*nvmem*" > set_ftrace_filter # Trace all nvmem filter functions | ||
{{Board$}} echo 1 > tracing_on # start ftrace | {{Board$}}echo 1 > tracing_on # start ftrace | ||
{{Board$}} hexdump -C -v /sys/bus/nvmem/devices/stm32-romem0/nvmem # dump nvmem | {{Board$}}hexdump -C -v /sys/bus/nvmem/devices/stm32-romem0/nvmem # dump nvmem | ||
00000000 17 00 00 00 01 80 00 00 00 00 00 00 00 00 00 00 |................| | 00000000 17 00 00 00 01 80 00 00 00 00 00 00 00 00 00 00 |................| | ||
... | ... | ||
{{Board$}} echo 0 > tracing_on # stop ftrace | {{Board$}}echo 0 > tracing_on # stop ftrace | ||
{{Board$}} cat trace | {{Board$}}cat trace | ||
# tracer: function | # tracer: function | ||
# | # | ||
Line 126: | Line 223: | ||
<noinclude> | <noinclude> | ||
{{ArticleBasedOnModel | Framework_overview_article_model}} | {{ArticleBasedOnModel | Framework_overview_article_model}} | ||
{{PublicationRequestId | | {{PublicationRequestId | 26423 | 2023-03-10 | (previous :10397 AnneJ)}} | ||
[[Category:Persistent storage]] | [[Category:Persistent storage]] | ||
</noinclude> | </noinclude> |
Latest revision as of 14:18, 24 June 2025
This article introduces how the NVMEM Linux® framework manages Non Volatile Memory data and how to read/write from/to it.
1. Framework purpose[edit | edit source]
The NVMEM Linux® framework provides a generic interface for non-volatile memory data devices such as:
- OTP (one-time programmable) fuses, for example BSEC OTP
- EEPROM
- Battery backed memory, for example TAMP backup registers
It offers kernel space and user space interfaces to read/write data such as analog calibration data or MAC address.
2. System overview[edit | edit source]
2.1. Component description[edit | edit source]
- NVMEM user (user space)
The user can use the NVMEM sysfs interface from a user terminal or a custom application to read/write data from/to NVMEM devices, and from user space.
- NVMEM user (kernel space)
The 'foo_driver' could be any driver in kernel space that uses the NVMEM API to read/write data from/to NVMEM devices (such as the analog calibration data used by an ADC driver).
- NVMEM framework (kernel space)
The NVMEM core provides sysfs interface and NVMEM API. They can be used to implement NVMEM user and NVMEM controller drivers.
- NVMEM drivers (kernel space) :
- STM32 ROMEM Linux® driver that exposes BSEC OTP data to the core.
- STM32 TAMP NVRAM Linux®driver that exposes non secure backup registers to the core.
- TEE framework (kernel space)
The TEE framework provides TEE client API to communicate with secure services, as the services provided by the OP-TEE Linux® driver.
- OP-TEE (Secure)
The OP-TEE secure OS is running on the Cortex-A in secure mode and exposes secure service with interfaces such as BSEC PTA and TA STM32MP NVMEM.
- NVMEM hardware
NVMEM controllers such as the BSEC internal peripheral for OTP or TAMP internal peripheral for Backup Registers.
2.2. API description[edit | edit source]
The NVMEM kernel documentation describes in driver-api/nvmem.html:
- Kernel space API
- for NVMEM providers (include/linux/nvmem-provider.h )
- for NVMEM consumers (include/linux/nvmem-consumer.h ),
- User space binary interface (sysfs) for sysfs-bus-nvmem documentation.
3. Configuration[edit | edit source]
3.1. Kernel configuration[edit | edit source]
Activate NVMEM framework in the kernel configuration through the Linux® menuconfig tool (see Menuconfig or how to configure kernel) with CONFIG_NVMEM = y:
Device Drivers --->
[*] NVMEM Support --->
<*> STMicroelectronics STM32 factory-programmed memory support
3.2. Device tree configuration[edit | edit source]
The NVMEM data device tree bindings describe:
- The location of non-volatile memory data
- The NVMEM data providers (Documentation/devicetree/bindings/nvmem/nvmem.yaml ): BSEC and TAMP
- The NVMEM data consumers (Documentation/devicetree/bindings/nvmem/nvmem-consumer.yaml )
The BSEC internal peripheral device tree bindings are described in the BSEC device tree configuration article.
The TAMP internal peripheral device tree bindings are described in the TAMP device tree configuration article.
4. How to use the framework[edit | edit source]
4.1. How to use NVMEM with sysfs interface[edit | edit source]
4.1.1. How to list NVMEM devices[edit | edit source]
The available NVMEM devices can be listed in sysfs directory /sys/bus/nvmem/devices.
Example of listing nvmem devices:
- BSEC is stm32-romem0
- TAMP Backup Registers is stm32-tamp-nvram0
ls /sys/bus/nvmem/devices/
stm32-romem0
stm32-tamp-nvram0
4.1.2. How to read OTP areas using NVMEM[edit | edit source]
The user space can read/write the raw NVMEM file located at /sys/bus/nvmem/devices/*/nvmem.
For BSEC, the NVMEM is the stm32-romem0 device. The content of non-secure OTP areas can be read but the secured OTP areas are masked, and their values replaced by 0.
On STM32MP1 series, only lower OTPs (OTP 0 to 31) are accessible by the non-secure world by default. The upper OTP data being restricted to security. If the user needs more than the lower OTP data, this can be managed by an exception described in OP-TEE device tree.
On STM32MP2 series, lower and middle OTPs (OTP 0 to 255) are accessible by the non-secure world. The device tree on STM32MP2 series does not support exception to give read-access to upper OTP (see OP-TEE device tree page for details).
- Example of reading all nvmem data on stm32-romem0 devices
dd if=/sys/bus/nvmem/devices/stm32-romem0/nvmem of=/tmp/file
- Example of displaying all nvmem data
hexdump -C -v /sys/bus/nvmem/devices/stm32-romem0/nvmem
4.1.3. How to write BSEC OTP data using NVMEM[edit | edit source]
The BSEC OTP areas can be written by 32-bit word starting at OTP N, as follows:
write OTP N word by word dd if=/tmp/file of=/sys/bus/nvmem/devices/stm32-romem0/nvmem bs=4 seek=N#
or
write OTP N, all the file in one request dd if=/tmp/file of=/sys/bus/nvmem/devices/stm32-romem0/nvmem seek=4*N oflag=seek_bytes#
With a file /tmp/file containing the OTP data to write, its size is 32-bit word aligned, for example:
OTP echo -n -e '\x01\x00\x00\x00' > /tmp/file # Create a 8 bytes length file, here 0x67452301 0xEFCDAB89 to update two OTPs echo -n -e '\x01\x23\x45\x67\x89\xAB\xCD\xEF' > /tmp/file# Create a 4 bytes length file filled with ones, e.g. 0xffffffff) dd if=/dev/zero count=1 bs=4 | tr '\000' '\377' > file # Create a 4 bytes length file, here 0x00000001 to update one
A lower OTP area can be written several times for a bit per bit update if it is not locked.
An upper OTP area can be written only if it is allowed in secure world device tree, and only once. When the upper OTP is written, it is permanent locked at the end of the NVMEM request to an avoid ECC issue on the second update. For the first example with bs = 4, this lock is performed after each OTP update, while for the second example with oflag = seek_bytes, it is done when all the OTP data in the input file are updated.
Below a compete example of writing the upper OTP 60:
'\x01\x23\x45\x67' > /tmp/file hexdump -C /tmp/file 00000000 01 23 45 67 |.#Eg| 00000004 dd if=/tmp/file of=/sys/bus/nvmem/devices/stm32-romem0/nvmem bs=4 seek=60 reboot << >> hexdump -C -v /sys/bus/nvmem/devices/stm32-romem0/nvmem .... 000000f0 01 23 45 67 00 00 00 00 00 00 00 00 00 00 00 00 |.#Eg............| ....echo -n -e
The associated output in STM32CubeProgrammer is:
OTP REGISTERS: --------------------------------------------------------------------------- ID | value | status --------------------------------------------------------------------------- ... 060 | 0x67452301 | 0x40000000 |_[30] Permanent write lock
or in U-Boot
fuse read 0 0 96
...
Word 0x0000003c: 67452301 00000000 00000000 00000000
...
4.2. How to use NVMEM with kernel space API[edit | edit source]
Here is an example of the kernel space API.
To describe the memory area, the device tree must include a node with the properties nvmem-cells and nvmem-cell-names. An example for the backup register can be found in TAMP device tree configuration.
&my_device_tree_node {
nvmem-cells = <&phandle_cell>;
nvmem-cell-names = "nvmem_cell_name";
}
Invoke nvmem_cell_get to get your nvmem_cell within your driver. The functions nvmem_cell_read and nvmem_cell_write allows to read or write the memory area.
struct nvmem_cell *my_cell = nvmem_cell_get(my_driver_dev, "nvmem_cell_name");
if (IS_ERR_OR_NULL(my_cell)) {
dev_err(my_driver_dev, "No cell for my device %ld\n", PTR_ERR(my_cell));
return PTR_ERR(my_cell);
}
//Read the cell
int my_cell_length = 0;
int* my_cell_content = nvmem_cell_read(my_cell, &my_cell_length);
*my_cell_content += 1;
//Update the cell
nvmem_cell_write(my_cell, &my_cell_length,sizeof(int));
...
5. How to trace the framework[edit | edit source]
Ftrace can be used to trace the NVMEM framework:
cd /sys/kernel/debug/tracing
cat available_filter_functions | grep nvmem # Show available filter functions
rtc_nvmem_register
rtc_nvmem_unregister
nvmem_reg_read
bin_attr_nvmem_read
...
Enable the kernel function tracer, then start using nvmem and display the result:
CPU# |||| TIMESTAMP FUNCTION # | | | |||| | | hexdump-478 [000] .... 423.502278: bin_attr_nvmem_read <-sysfs_kf_bin_read hexdump-478 [000] .... 423.502290: nvmem_reg_read <-bin_attr_nvmem_read hexdump-478 [000] .... 423.515804: bin_attr_nvmem_read <-sysfs_kf_bin_readecho function > current_tracer echo "*nvmem*" > set_ftrace_filter # Trace all nvmem filter functions echo 1 > tracing_on # start ftrace hexdump -C -v /sys/bus/nvmem/devices/stm32-romem0/nvmem # dump nvmem 00000000 17 00 00 00 01 80 00 00 00 00 00 00 00 00 00 00 |................| ... echo 0 > tracing_on # stop ftrace cat trace # tracer: function # # _-----=> irqs-off # / _----=> need-resched # | / _---=> hardirq/softirq # || / _--=> preempt-depth # ||| / delay # TASK-PID
6. References[edit | edit source]