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