Blame view
Documentation/driver-api/nvmem.rst
6.28 KB
baa293e95 docs: driver-api:... |
1 |
.. SPDX-License-Identifier: GPL-2.0 |
a278295cc docs: nvmem: conv... |
2 3 4 5 6 7 |
=============== NVMEM Subsystem =============== Srinivas Kandagatla <srinivas.kandagatla@linaro.org> |
354ebb541 Documentation: nv... |
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 |
This document explains the NVMEM Framework along with the APIs provided, and how to use it. 1. Introduction =============== *NVMEM* is the abbreviation for Non Volatile Memory layer. It is used to retrieve configuration of SOC or Device specific data from non volatile memories like eeprom, efuses and so on. Before this framework existed, NVMEM drivers like eeprom were stored in drivers/misc, where they all had to duplicate pretty much the same code to register a sysfs file, allow in-kernel users to access the content of the devices they were driving, etc. This was also a problem as far as other in-kernel users were involved, since the solutions used were pretty much different from one driver to another, there was a rather big abstraction leak. This framework aims at solve these problems. It also introduces DT representation for consumer devices to go get the data they require (MAC Addresses, SoC/Revision ID, part numbers, and so on) from the NVMEMs. This framework is based on regmap, so that most of the abstraction available in regmap can be reused, across multiple types of buses. NVMEM Providers +++++++++++++++ NVMEM provider refers to an entity that implements methods to initialize, read and write the non-volatile memory. 2. Registering/Unregistering the NVMEM provider =============================================== A NVMEM provider can register with NVMEM core by supplying relevant nvmem configuration to nvmem_register(), on success core would return a valid nvmem_device pointer. nvmem_unregister(nvmem) is used to unregister a previously registered provider. |
a278295cc docs: nvmem: conv... |
47 |
For example, a simple qfprom case:: |
354ebb541 Documentation: nv... |
48 |
|
a278295cc docs: nvmem: conv... |
49 |
static struct nvmem_config econfig = { |
354ebb541 Documentation: nv... |
50 51 |
.name = "qfprom", .owner = THIS_MODULE, |
a278295cc docs: nvmem: conv... |
52 |
}; |
354ebb541 Documentation: nv... |
53 |
|
a278295cc docs: nvmem: conv... |
54 55 |
static int qfprom_probe(struct platform_device *pdev) { |
354ebb541 Documentation: nv... |
56 57 58 59 |
... econfig.dev = &pdev->dev; nvmem = nvmem_register(&econfig); ... |
a278295cc docs: nvmem: conv... |
60 |
} |
354ebb541 Documentation: nv... |
61 62 63 |
It is mandatory that the NVMEM provider has a regmap associated with its struct device. Failure to do would return error code from nvmem_register(). |
4903d19c2 Documentation: nv... |
64 |
Users of board files can define and register nvmem cells using the |
a278295cc docs: nvmem: conv... |
65 |
nvmem_cell_table struct:: |
4903d19c2 Documentation: nv... |
66 |
|
a278295cc docs: nvmem: conv... |
67 |
static struct nvmem_cell_info foo_nvmem_cells[] = { |
4903d19c2 Documentation: nv... |
68 69 70 71 72 |
{ .name = "macaddr", .offset = 0x7f00, .bytes = ETH_ALEN, } |
a278295cc docs: nvmem: conv... |
73 |
}; |
4903d19c2 Documentation: nv... |
74 |
|
a278295cc docs: nvmem: conv... |
75 |
static struct nvmem_cell_table foo_nvmem_cell_table = { |
4903d19c2 Documentation: nv... |
76 77 78 |
.nvmem_name = "i2c-eeprom", .cells = foo_nvmem_cells, .ncells = ARRAY_SIZE(foo_nvmem_cells), |
a278295cc docs: nvmem: conv... |
79 |
}; |
4903d19c2 Documentation: nv... |
80 |
|
a278295cc docs: nvmem: conv... |
81 |
nvmem_add_cell_table(&foo_nvmem_cell_table); |
4903d19c2 Documentation: nv... |
82 83 |
Additionally it is possible to create nvmem cell lookup entries and register |
a278295cc docs: nvmem: conv... |
84 |
them with the nvmem framework from machine code as shown in the example below:: |
4903d19c2 Documentation: nv... |
85 |
|
a278295cc docs: nvmem: conv... |
86 |
static struct nvmem_cell_lookup foo_nvmem_lookup = { |
4903d19c2 Documentation: nv... |
87 88 89 90 |
.nvmem_name = "i2c-eeprom", .cell_name = "macaddr", .dev_id = "foo_mac.0", .con_id = "mac-address", |
a278295cc docs: nvmem: conv... |
91 |
}; |
4903d19c2 Documentation: nv... |
92 |
|
a278295cc docs: nvmem: conv... |
93 |
nvmem_add_cell_lookups(&foo_nvmem_lookup, 1); |
4903d19c2 Documentation: nv... |
94 |
|
354ebb541 Documentation: nv... |
95 96 97 98 99 100 101 102 103 104 |
NVMEM Consumers +++++++++++++++ NVMEM consumers are the entities which make use of the NVMEM provider to read from and to NVMEM. 3. NVMEM cell based consumer APIs ================================= NVMEM cells are the data entries/fields in the NVMEM. |
a278295cc docs: nvmem: conv... |
105 |
The NVMEM framework provides 3 APIs to read/write NVMEM cells:: |
354ebb541 Documentation: nv... |
106 |
|
a278295cc docs: nvmem: conv... |
107 108 |
struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *name); struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *name); |
354ebb541 Documentation: nv... |
109 |
|
a278295cc docs: nvmem: conv... |
110 111 |
void nvmem_cell_put(struct nvmem_cell *cell); void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell); |
354ebb541 Documentation: nv... |
112 |
|
a278295cc docs: nvmem: conv... |
113 114 |
void *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len); int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len); |
354ebb541 Documentation: nv... |
115 |
|
a278295cc docs: nvmem: conv... |
116 |
`*nvmem_cell_get()` apis will get a reference to nvmem cell for a given id, |
354ebb541 Documentation: nv... |
117 |
and nvmem_cell_read/write() can then read or write to the cell. |
a278295cc docs: nvmem: conv... |
118 119 |
Once the usage of the cell is finished the consumer should call `*nvmem_cell_put()` to free all the allocation memory for the cell. |
354ebb541 Documentation: nv... |
120 121 122 123 124 |
4. Direct NVMEM device based consumer APIs ========================================== In some instances it is necessary to directly read/write the NVMEM. |
a278295cc docs: nvmem: conv... |
125 |
To facilitate such consumers NVMEM framework provides below apis:: |
354ebb541 Documentation: nv... |
126 |
|
a278295cc docs: nvmem: conv... |
127 128 |
struct nvmem_device *nvmem_device_get(struct device *dev, const char *name); struct nvmem_device *devm_nvmem_device_get(struct device *dev, |
354ebb541 Documentation: nv... |
129 |
const char *name); |
8c2a2b8c2 nvmem: core: add ... |
130 131 |
struct nvmem_device *nvmem_device_find(void *data, int (*match)(struct device *dev, const void *data)); |
a278295cc docs: nvmem: conv... |
132 133 |
void nvmem_device_put(struct nvmem_device *nvmem); int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset, |
354ebb541 Documentation: nv... |
134 |
size_t bytes, void *buf); |
a278295cc docs: nvmem: conv... |
135 |
int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset, |
354ebb541 Documentation: nv... |
136 |
size_t bytes, void *buf); |
a278295cc docs: nvmem: conv... |
137 |
int nvmem_device_cell_read(struct nvmem_device *nvmem, |
354ebb541 Documentation: nv... |
138 |
struct nvmem_cell_info *info, void *buf); |
a278295cc docs: nvmem: conv... |
139 |
int nvmem_device_cell_write(struct nvmem_device *nvmem, |
354ebb541 Documentation: nv... |
140 141 142 |
struct nvmem_cell_info *info, void *buf); Before the consumers can read/write NVMEM directly, it should get hold |
a278295cc docs: nvmem: conv... |
143 |
of nvmem_controller from one of the `*nvmem_device_get()` api. |
354ebb541 Documentation: nv... |
144 145 146 147 148 149 |
The difference between these apis and cell based apis is that these apis always take nvmem_device as parameter. 5. Releasing a reference to the NVMEM ===================================== |
be629b441 NVMEM documentati... |
150 |
When a consumer no longer needs the NVMEM, it has to release the reference |
354ebb541 Documentation: nv... |
151 |
to the NVMEM it has obtained using the APIs mentioned in the above section. |
a278295cc docs: nvmem: conv... |
152 |
The NVMEM framework provides 2 APIs to release a reference to the NVMEM:: |
354ebb541 Documentation: nv... |
153 |
|
a278295cc docs: nvmem: conv... |
154 155 156 157 |
void nvmem_cell_put(struct nvmem_cell *cell); void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell); void nvmem_device_put(struct nvmem_device *nvmem); void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem); |
354ebb541 Documentation: nv... |
158 159 160 161 162 163 164 165 166 167 |
Both these APIs are used to release a reference to the NVMEM and devm_nvmem_cell_put and devm_nvmem_device_put destroys the devres associated with this NVMEM. Userspace +++++++++ 6. Userspace binary interface ============================== |
a278295cc docs: nvmem: conv... |
168 169 170 |
Userspace can read/write the raw NVMEM file located at:: /sys/bus/nvmem/devices/*/nvmem |
354ebb541 Documentation: nv... |
171 |
|
a278295cc docs: nvmem: conv... |
172 |
ex:: |
354ebb541 Documentation: nv... |
173 |
|
a278295cc docs: nvmem: conv... |
174 |
hexdump /sys/bus/nvmem/devices/qfprom0/nvmem |
354ebb541 Documentation: nv... |
175 |
|
a278295cc docs: nvmem: conv... |
176 177 178 179 180 181 182 |
0000000 0000 0000 0000 0000 0000 0000 0000 0000 * 00000a0 db10 2240 0000 e000 0c00 0c00 0000 0c00 0000000 0000 0000 0000 0000 0000 0000 0000 0000 ... * 0001000 |
354ebb541 Documentation: nv... |
183 184 185 186 187 |
7. DeviceTree Binding ===================== See Documentation/devicetree/bindings/nvmem/nvmem.txt |