1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * nvmem framework provider. |
4 | * |
5 | * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org> |
6 | * Copyright (C) 2013 Maxime Ripard <maxime.ripard@free-electrons.com> |
7 | */ |
8 | |
9 | #ifndef _LINUX_NVMEM_PROVIDER_H |
10 | #define _LINUX_NVMEM_PROVIDER_H |
11 | |
12 | #include <linux/device.h> |
13 | #include <linux/device/driver.h> |
14 | #include <linux/err.h> |
15 | #include <linux/errno.h> |
16 | #include <linux/gpio/consumer.h> |
17 | |
18 | struct nvmem_device; |
19 | typedef int (*nvmem_reg_read_t)(void *priv, unsigned int offset, |
20 | void *val, size_t bytes); |
21 | typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset, |
22 | void *val, size_t bytes); |
23 | /* used for vendor specific post processing of cell data */ |
24 | typedef int (*nvmem_cell_post_process_t)(void *priv, const char *id, int index, |
25 | unsigned int offset, void *buf, |
26 | size_t bytes); |
27 | |
28 | enum nvmem_type { |
29 | NVMEM_TYPE_UNKNOWN = 0, |
30 | NVMEM_TYPE_EEPROM, |
31 | NVMEM_TYPE_OTP, |
32 | NVMEM_TYPE_BATTERY_BACKED, |
33 | NVMEM_TYPE_FRAM, |
34 | }; |
35 | |
36 | #define NVMEM_DEVID_NONE (-1) |
37 | #define NVMEM_DEVID_AUTO (-2) |
38 | |
39 | /** |
40 | * struct nvmem_keepout - NVMEM register keepout range. |
41 | * |
42 | * @start: The first byte offset to avoid. |
43 | * @end: One beyond the last byte offset to avoid. |
44 | * @value: The byte to fill reads with for this region. |
45 | */ |
46 | struct nvmem_keepout { |
47 | unsigned int start; |
48 | unsigned int end; |
49 | unsigned char value; |
50 | }; |
51 | |
52 | /** |
53 | * struct nvmem_cell_info - NVMEM cell description |
54 | * @name: Name. |
55 | * @offset: Offset within the NVMEM device. |
56 | * @raw_len: Length of raw data (without post processing). |
57 | * @bytes: Length of the cell. |
58 | * @bit_offset: Bit offset if cell is smaller than a byte. |
59 | * @nbits: Number of bits. |
60 | * @np: Optional device_node pointer. |
61 | * @read_post_process: Callback for optional post processing of cell data |
62 | * on reads. |
63 | * @priv: Opaque data passed to the read_post_process hook. |
64 | */ |
65 | struct nvmem_cell_info { |
66 | const char *name; |
67 | unsigned int offset; |
68 | size_t raw_len; |
69 | unsigned int bytes; |
70 | unsigned int bit_offset; |
71 | unsigned int nbits; |
72 | struct device_node *np; |
73 | nvmem_cell_post_process_t read_post_process; |
74 | void *priv; |
75 | }; |
76 | |
77 | /** |
78 | * struct nvmem_config - NVMEM device configuration |
79 | * |
80 | * @dev: Parent device. |
81 | * @name: Optional name. |
82 | * @id: Optional device ID used in full name. Ignored if name is NULL. |
83 | * @owner: Pointer to exporter module. Used for refcounting. |
84 | * @cells: Optional array of pre-defined NVMEM cells. |
85 | * @ncells: Number of elements in cells. |
86 | * @add_legacy_fixed_of_cells: Read fixed NVMEM cells from old OF syntax. |
87 | * @fixup_dt_cell_info: Will be called before a cell is added. Can be |
88 | * used to modify the nvmem_cell_info. |
89 | * @keepout: Optional array of keepout ranges (sorted ascending by start). |
90 | * @nkeepout: Number of elements in the keepout array. |
91 | * @type: Type of the nvmem storage |
92 | * @read_only: Device is read-only. |
93 | * @root_only: Device is accessibly to root only. |
94 | * @of_node: If given, this will be used instead of the parent's of_node. |
95 | * @reg_read: Callback to read data. |
96 | * @reg_write: Callback to write data. |
97 | * @size: Device size. |
98 | * @word_size: Minimum read/write access granularity. |
99 | * @stride: Minimum read/write access stride. |
100 | * @priv: User context passed to read/write callbacks. |
101 | * @ignore_wp: Write Protect pin is managed by the provider. |
102 | * @layout: Fixed layout associated with this nvmem device. |
103 | * |
104 | * Note: A default "nvmem<id>" name will be assigned to the device if |
105 | * no name is specified in its configuration. In such case "<id>" is |
106 | * generated with ida_simple_get() and provided id field is ignored. |
107 | * |
108 | * Note: Specifying name and setting id to -1 implies a unique device |
109 | * whose name is provided as-is (kept unaltered). |
110 | */ |
111 | struct nvmem_config { |
112 | struct device *dev; |
113 | const char *name; |
114 | int id; |
115 | struct module *owner; |
116 | const struct nvmem_cell_info *cells; |
117 | int ncells; |
118 | bool add_legacy_fixed_of_cells; |
119 | void (*fixup_dt_cell_info)(struct nvmem_device *nvmem, |
120 | struct nvmem_cell_info *cell); |
121 | const struct nvmem_keepout *keepout; |
122 | unsigned int nkeepout; |
123 | enum nvmem_type type; |
124 | bool read_only; |
125 | bool root_only; |
126 | bool ignore_wp; |
127 | struct nvmem_layout *layout; |
128 | struct device_node *of_node; |
129 | nvmem_reg_read_t reg_read; |
130 | nvmem_reg_write_t reg_write; |
131 | int size; |
132 | int word_size; |
133 | int stride; |
134 | void *priv; |
135 | /* To be only used by old driver/misc/eeprom drivers */ |
136 | bool compat; |
137 | struct device *base_dev; |
138 | }; |
139 | |
140 | /** |
141 | * struct nvmem_cell_table - NVMEM cell definitions for given provider |
142 | * |
143 | * @nvmem_name: Provider name. |
144 | * @cells: Array of cell definitions. |
145 | * @ncells: Number of cell definitions in the array. |
146 | * @node: List node. |
147 | * |
148 | * This structure together with related helper functions is provided for users |
149 | * that don't can't access the nvmem provided structure but wish to register |
150 | * cell definitions for it e.g. board files registering an EEPROM device. |
151 | */ |
152 | struct nvmem_cell_table { |
153 | const char *nvmem_name; |
154 | const struct nvmem_cell_info *cells; |
155 | size_t ncells; |
156 | struct list_head node; |
157 | }; |
158 | |
159 | /** |
160 | * struct nvmem_layout - NVMEM layout definitions |
161 | * |
162 | * @dev: Device-model layout device. |
163 | * @nvmem: The underlying NVMEM device |
164 | * @add_cells: Will be called if a nvmem device is found which |
165 | * has this layout. The function will add layout |
166 | * specific cells with nvmem_add_one_cell(). |
167 | * |
168 | * A nvmem device can hold a well defined structure which can just be |
169 | * evaluated during runtime. For example a TLV list, or a list of "name=val" |
170 | * pairs. A nvmem layout can parse the nvmem device and add appropriate |
171 | * cells. |
172 | */ |
173 | struct nvmem_layout { |
174 | struct device dev; |
175 | struct nvmem_device *nvmem; |
176 | int (*add_cells)(struct nvmem_layout *layout); |
177 | }; |
178 | |
179 | struct nvmem_layout_driver { |
180 | struct device_driver driver; |
181 | int (*probe)(struct nvmem_layout *layout); |
182 | void (*remove)(struct nvmem_layout *layout); |
183 | }; |
184 | |
185 | #if IS_ENABLED(CONFIG_NVMEM) |
186 | |
187 | struct nvmem_device *nvmem_register(const struct nvmem_config *cfg); |
188 | void nvmem_unregister(struct nvmem_device *nvmem); |
189 | |
190 | struct nvmem_device *devm_nvmem_register(struct device *dev, |
191 | const struct nvmem_config *cfg); |
192 | |
193 | void nvmem_add_cell_table(struct nvmem_cell_table *table); |
194 | void nvmem_del_cell_table(struct nvmem_cell_table *table); |
195 | |
196 | int nvmem_add_one_cell(struct nvmem_device *nvmem, |
197 | const struct nvmem_cell_info *info); |
198 | |
199 | int nvmem_layout_register(struct nvmem_layout *layout); |
200 | void nvmem_layout_unregister(struct nvmem_layout *layout); |
201 | |
202 | int nvmem_layout_driver_register(struct nvmem_layout_driver *drv); |
203 | void nvmem_layout_driver_unregister(struct nvmem_layout_driver *drv); |
204 | #define module_nvmem_layout_driver(__nvmem_layout_driver) \ |
205 | module_driver(__nvmem_layout_driver, nvmem_layout_driver_register, \ |
206 | nvmem_layout_driver_unregister) |
207 | |
208 | #else |
209 | |
210 | static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c) |
211 | { |
212 | return ERR_PTR(-EOPNOTSUPP); |
213 | } |
214 | |
215 | static inline void nvmem_unregister(struct nvmem_device *nvmem) {} |
216 | |
217 | static inline struct nvmem_device * |
218 | devm_nvmem_register(struct device *dev, const struct nvmem_config *c) |
219 | { |
220 | return nvmem_register(c); |
221 | } |
222 | |
223 | static inline void nvmem_add_cell_table(struct nvmem_cell_table *table) {} |
224 | static inline void nvmem_del_cell_table(struct nvmem_cell_table *table) {} |
225 | static inline int nvmem_add_one_cell(struct nvmem_device *nvmem, |
226 | const struct nvmem_cell_info *info) |
227 | { |
228 | return -EOPNOTSUPP; |
229 | } |
230 | |
231 | static inline int nvmem_layout_register(struct nvmem_layout *layout) |
232 | { |
233 | return -EOPNOTSUPP; |
234 | } |
235 | |
236 | static inline void nvmem_layout_unregister(struct nvmem_layout *layout) {} |
237 | |
238 | #endif /* CONFIG_NVMEM */ |
239 | |
240 | #if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF) |
241 | |
242 | /** |
243 | * of_nvmem_layout_get_container() - Get OF node of layout container |
244 | * |
245 | * @nvmem: nvmem device |
246 | * |
247 | * Return: a node pointer with refcount incremented or NULL if no |
248 | * container exists. Use of_node_put() on it when done. |
249 | */ |
250 | struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem); |
251 | |
252 | #else /* CONFIG_NVMEM && CONFIG_OF */ |
253 | |
254 | static inline struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem) |
255 | { |
256 | return NULL; |
257 | } |
258 | |
259 | #endif /* CONFIG_NVMEM && CONFIG_OF */ |
260 | |
261 | #endif /* ifndef _LINUX_NVMEM_PROVIDER_H */ |
262 | |