blob: 56f5040cfcd9102747070ec48801e7b9ad6b1ffa (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
@page page_device_nvmem_dm NVMEM device model (DM)
# NVMEM under `RT_USING_DM`
**`RT_USING_NVMEM`** builds **`nvmem.c`** only. **Provider** drivers register **`struct rt_nvmem_device`** and set **`rt_ofw_data(provider_np)`**. **Consumers** parse **`nvmem-cells`** phandles.
API: @ref page_device_nvmem. Sources: **`nvmem.c`**, **`nvmem.h`**.
---
## Kconfig
| Option | Role |
| --- | --- |
| **`RT_USING_DM`** | Required |
| **`RT_USING_OFW`** | Required |
| **`RT_USING_PIN`** | Optional **`wp`** GPIO |
| **`RT_USING_NVMEM`** | Core; selects **`RT_USING_ADT_REF`** |
| **`SOC_DM_NVMEM_DIR`** | BSP OTP/eFuse/EEPROM drivers |
No **`rt_bus`** — provider **`reg_read`/`reg_write`** + OFW lookup only.
---
## Architecture
```
BSP provider (efuse/otp/eeprom)
| rt_nvmem_device_register, rt_ofw_data = ndev
v
Consumer: nvmem-cells = <&provider N>;
v
rt_nvmem_get_cell_by_name → rt_nvmem_cell_read/write
v
rt_nvmem_put_cell
```
---
## Provider DT
```dts
efuse: efuse@110000 {
compatible = "vendor,soc-efuse";
reg = <0x110000 0x1000>;
#address-cells = <1>;
#size-cells = <1>;
#nvmem-cell-cells = <1>;
read-only;
mac@0 { reg = <0x00 0x06>; };
};
```
| Property | Role |
| --- | --- |
| **`#nvmem-cell-cells`** | Usually **1** — phandle arg = cell index |
| **`read-only`** | Forces read-only at register |
| **`wp`** | Write-protect GPIO (unless **`ignore_wp`**) |
---
## Consumer DT
```dts
gmac: ethernet@0 {
nvmem-cells = <&efuse 0>;
nvmem-cell-names = "mac-address";
};
```
**`ofw_nvmem_get_cell`** order:
1. **`rt_ofw_data(cell_np)`** if cached
2. Match **`append_cell`** static list by index/id
3. Allocate dynamic cell from child **`reg`** (**`offset`**, **`bytes`**)
Dynamic cells are **`free_able`** and removed on last **`put_cell`**.
---
## Provider checklist
1. Implement **`reg_read`**; **`reg_write`** only if programmable.
2. Set **`size`**, **`parent.ofw_node`**, callbacks.
3. **`rt_nvmem_device_register`**.
4. Optional **`append_cell`** for fixed index/id layouts.
5. **`remove`**: all **`put_cell`**, then **`unregister`** when ref is 1.
6. Add driver under **`SOC_DM_NVMEM_DIR`**.
---
## Bit-packed cells
**`bit_offset`** / **`nbits`** on **`struct rt_nvmem_cell`**: core masks after byte read; write merges into existing bytes. Prefer byte-aligned **`reg = <offset length>`**; validate parsing in **`nvmem.c`** or use **`append_cell`**.
---
## Pitfalls
| Issue | Mitigation |
| --- | --- |
| Provider not probed | **`rt_platform_ofw_request`** first |
| **`#nvmem-cell-cells` mismatch** | Match provider binding |
| Concurrent OTP | Serialize in **`reg_read`/`reg_write`** |
| **`unregister` EBUSY** | Release all cell refs |
---
## See also
- @ref page_device_nvmem
- @ref page_device_iio_dm
- @ref page_device_ofw
|