xref: /optee_os/core/include/drivers/nvmem.h (revision af3fb62410645ac9636d27c3d1db72c0c9fca913)
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3  * Copyright (c) 2023, Microchip
4  */
5 
6 #ifndef __DRIVERS_NVMEM_H
7 #define __DRIVERS_NVMEM_H
8 
9 #include <kernel/dt_driver.h>
10 #include <tee_api_defines.h>
11 #include <tee_api_types.h>
12 #include <types_ext.h>
13 
14 struct nvmem_cell;
15 
16 /*
17  * struct nvmem_ops - NVMEM device driver operations
18  * @read_cell: Allocate @data in the heap and load @len bytes to from an
19  * NVMEM cell
20  * @put_cell: Release resources allocated from nvmem_dt_get_func callback
21  * function
22  */
23 struct nvmem_ops {
24 	/*
25 	 * Read data from an NVMEM cell.
26 	 * @cell: Cell to read data from
27 	 * @data: Output buffer of size greater or equal to @cell->size
28 	 */
29 	TEE_Result (*read_cell)(struct nvmem_cell *cell, uint8_t *data);
30 	void (*put_cell)(struct nvmem_cell *cell);
31 };
32 
33 /*
34  * struct nvmem_cell - Description of an NVMEM cell
35  * @offset: Cell byte offset in the NVMEM device
36  * @len: Cell byte size
37  * @ops: NVMEM device driver operation handlers
38  * @drv_data: NVMEM device driver private data
39  */
40 struct nvmem_cell {
41 	paddr_t offset;
42 	size_t len;
43 	const struct nvmem_ops *ops;
44 	void *drv_data;
45 };
46 
47 /*
48  * nvmem_dt_get_func - Typedef of handlers to get an NVMEM cell from a npode
49  * @args: Reference to phandle arguments
50  * @data: Pointer to data given at nvmem_dt_get_func() call
51  * @cell: Output reference to cell instance upon success
52  *
53  * Return TEE_SUCCESS in case of success.
54  * Return TEE_ERROR_DEFER_DRIVER_INIT if NVMEM driver is not initialized
55  * Return another TEE_Result compliant code otherwise.
56  */
57 typedef TEE_Result (*nvmem_dt_get_func)(struct dt_pargs *args,
58 					void *data, struct nvmem_cell **cell);
59 
60 #ifdef CFG_DRIVERS_NVMEM
61 /**
62  * nvmem_register_provider() - Register a NVMEM controller
63  *
64  * @fdt: Device tree to work on
65  * @nodeoffset: Node offset of NVMEM cell consumer
66  * @get_dt_nvmem: Callback to match the devicetree NVMEM reference with
67  * nvmem_cell
68  * @data: Data which will be passed to the get_dt_nvmem callback
69  * Return a TEE_Result compliant value
70  */
71 static inline TEE_Result nvmem_register_provider(const void *fdt,
72 						 int nodeoffset,
73 						 nvmem_dt_get_func get_dt_nvmem,
74 						 void *data)
75 {
76 	return dt_driver_register_provider(fdt, nodeoffset,
77 					   (get_of_device_func)get_dt_nvmem,
78 					   data, DT_DRIVER_NVMEM);
79 }
80 
81 /**
82  * nvmem_get_cell_by_name() - Obtain a NVMEM cell from its name in the DT node
83  *
84  * @fdt: Device tree to work on
85  * @nodeoffset: Node offset of NVMEM cell consumer
86  * @name: name of the NVMEM cell defined by property nvmem-cell-names to obtain
87  * from the device tree
88  * @cell: Pointer filled with the retrieved cell, must be freed after use
89    using nvmem_put_cell()
90  * Return a TEE_Result compliant value
91  */
92 TEE_Result nvmem_get_cell_by_name(const void *fdt, int nodeoffset,
93 				  const char *name, struct nvmem_cell **cell);
94 
95 /**
96  * nvmem_get_cell_by_index() - Obtain a NVMEM cell from property nvmem-cells
97  *
98  * @fdt: Device tree to work on
99  * @nodeoffset: Node offset of NVMEM cell consumer
100  * @index: Index of the NVMEM cell to obtain from device-tree
101  * @out_cell: Pointer filled with the retrieved cell, must be freed after use
102  * using nvmem_put_cell()
103  * Return a TEE_Result compliant value
104  */
105 TEE_Result nvmem_get_cell_by_index(const void *fdt,
106 				   int nodeoffset,
107 				   unsigned int index,
108 				   struct nvmem_cell **out_cell);
109 
110 /**
111  * nvmem_cell_parse_dt() - Parse device-tree information to fill a NVMEM cell
112  *
113  * @fdt: Device tree to work on
114  * @nodeoffset: Node offset of the NVMEM cell controller
115  * @cell: Pointer to cell that will be filled
116  */
117 TEE_Result nvmem_cell_parse_dt(const void *fdt, int nodeoffset,
118 			       struct nvmem_cell *cell);
119 
120 /**
121  * nvmem_put_cell() - Free resource allocated from nvmem_get_cell_by_*()
122  *
123  * @cell: Cell to be freed
124  */
125 static inline void nvmem_put_cell(struct nvmem_cell *cell)
126 {
127 	if (cell->ops->put_cell)
128 		cell->ops->put_cell(cell);
129 }
130 
131 /*
132  * nvmem_cell_read() - Read data from a NVMEM cell
133  * @cell: Cell to read from NVMEM
134  * @data: Output data read from the cell upon success, byte size >= @cell->size
135  */
136 static inline TEE_Result nvmem_cell_read(struct nvmem_cell *cell,
137 					 uint8_t *data)
138 {
139 	if (!cell->ops->read_cell)
140 		return TEE_ERROR_NOT_SUPPORTED;
141 
142 	return cell->ops->read_cell(cell, data);
143 }
144 
145 /*
146  * nvmem_cell_malloc_and_read() - Allocate and read data from a NVMEM cell
147  * @cell: Cell to read from NVMEM
148  * @data: Output allocated buffer where NVMEM cell data are stored upon success
149  *
150  * Upon success, the output buffer is allocated with malloc(). Caller is
151  * responsible for freeing the buffer with free() if needed.
152  */
153 TEE_Result nvmem_cell_malloc_and_read(struct nvmem_cell *cell,
154 				      uint8_t **out_data);
155 
156 #else /* CFG_DRIVERS_NVMEM */
157 static inline TEE_Result nvmem_register_provider(const void *fdt __unused,
158 						 int nodeoffset __unused,
159 						 nvmem_dt_get_func fn __unused,
160 						 void *data __unused)
161 {
162 	return TEE_ERROR_NOT_SUPPORTED;
163 }
164 
165 static inline TEE_Result nvmem_get_cell_by_name(const void *fdt __unused,
166 						int nodeoffset __unused,
167 						const char *name __unused,
168 						struct nvmem_cell **c __unused)
169 {
170 	return TEE_ERROR_NOT_SUPPORTED;
171 }
172 
173 static inline
174 TEE_Result nvmem_get_cell_by_index(const void *fdt __unused,
175 				   int nodeoffset __unused,
176 				   unsigned int index __unused,
177 				   struct nvmem_cell **cell __unused)
178 {
179 	return TEE_ERROR_NOT_SUPPORTED;
180 }
181 
182 static inline TEE_Result nvmem_cell_parse_dt(const void *fdt __unused,
183 					     int nodeoffset __unused,
184 					     struct nvmem_cell *cell __unused)
185 {
186 	return TEE_ERROR_NOT_SUPPORTED;
187 }
188 
189 static inline void nvmem_put_cell(struct nvmem_cell *cell __unused)
190 {
191 }
192 #endif /* CFG_DRIVERS_NVMEM */
193 #endif /* __DRIVERS_NVMEM_H */
194