summaryrefslogtreecommitdiff
path: root/documentation/6.components/device-driver/nvmem/dm.md
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