xref: /optee_os/core/drivers/nvmem/nvmem.c (revision 515c1ba9a5d652ebaeae43754635b5386a328721)
1*515c1ba9SClément Léger // SPDX-License-Identifier: BSD-2-Clause
2*515c1ba9SClément Léger /*
3*515c1ba9SClément Léger  * Copyright (c) 2023, Microchip
4*515c1ba9SClément Léger  */
5*515c1ba9SClément Léger 
6*515c1ba9SClément Léger #include <drivers/nvmem.h>
7*515c1ba9SClément Léger #include <kernel/dt.h>
8*515c1ba9SClément Léger #include <libfdt.h>
9*515c1ba9SClément Léger 
10*515c1ba9SClément Léger TEE_Result nvmem_cell_parse_dt(const void *fdt, int nodeoffset,
11*515c1ba9SClément Léger 			       struct nvmem_cell *cell)
12*515c1ba9SClément Léger {
13*515c1ba9SClément Léger 	size_t buf_len = 0;
14*515c1ba9SClément Léger 	paddr_t offset = 0;
15*515c1ba9SClément Léger 
16*515c1ba9SClément Léger 	buf_len = fdt_reg_size(fdt, nodeoffset);
17*515c1ba9SClément Léger 	if (buf_len == DT_INFO_INVALID_REG_SIZE)
18*515c1ba9SClément Léger 		return TEE_ERROR_GENERIC;
19*515c1ba9SClément Léger 
20*515c1ba9SClément Léger 	offset = fdt_reg_base_address(fdt, nodeoffset);
21*515c1ba9SClément Léger 	if (offset == DT_INFO_INVALID_REG)
22*515c1ba9SClément Léger 		return TEE_ERROR_GENERIC;
23*515c1ba9SClément Léger 
24*515c1ba9SClément Léger 	cell->len = buf_len;
25*515c1ba9SClément Léger 	cell->offset = offset;
26*515c1ba9SClément Léger 
27*515c1ba9SClément Léger 	return TEE_SUCCESS;
28*515c1ba9SClément Léger }
29*515c1ba9SClément Léger 
30*515c1ba9SClément Léger TEE_Result nvmem_get_cell_by_name(const void *fdt, int nodeoffset,
31*515c1ba9SClément Léger 				  const char *name, struct nvmem_cell **cell)
32*515c1ba9SClément Léger {
33*515c1ba9SClément Léger 	int index = 0;
34*515c1ba9SClément Léger 
35*515c1ba9SClément Léger 	index = fdt_stringlist_search(fdt, nodeoffset, "nvmem-cell-names",
36*515c1ba9SClément Léger 				      name);
37*515c1ba9SClément Léger 	if (index < 0)
38*515c1ba9SClément Léger 		return TEE_ERROR_ITEM_NOT_FOUND;
39*515c1ba9SClément Léger 
40*515c1ba9SClément Léger 	return nvmem_get_cell_by_index(fdt, nodeoffset, index, cell);
41*515c1ba9SClément Léger }
42*515c1ba9SClément Léger 
43*515c1ba9SClément Léger TEE_Result nvmem_get_cell_by_index(const void *fdt,
44*515c1ba9SClément Léger 				   int nodeoffset,
45*515c1ba9SClément Léger 				   unsigned int index,
46*515c1ba9SClément Léger 				   struct nvmem_cell **out_cell)
47*515c1ba9SClément Léger {
48*515c1ba9SClément Léger 	TEE_Result res = TEE_ERROR_GENERIC;
49*515c1ba9SClément Léger 	void *cell = NULL;
50*515c1ba9SClément Léger 
51*515c1ba9SClément Léger 	res = dt_driver_device_from_node_idx_prop("nvmem-cells", fdt,
52*515c1ba9SClément Léger 						  nodeoffset, index,
53*515c1ba9SClément Léger 						  DT_DRIVER_NVMEM, &cell);
54*515c1ba9SClément Léger 	if (!res)
55*515c1ba9SClément Léger 		*out_cell = cell;
56*515c1ba9SClément Léger 
57*515c1ba9SClément Léger 	return res;
58*515c1ba9SClément Léger }
59*515c1ba9SClément Léger 
60*515c1ba9SClément Léger TEE_Result nvmem_cell_malloc_and_read(struct nvmem_cell *cell,
61*515c1ba9SClément Léger 				      uint8_t **out_data)
62*515c1ba9SClément Léger {
63*515c1ba9SClément Léger 	TEE_Result res = TEE_ERROR_GENERIC;
64*515c1ba9SClément Léger 
65*515c1ba9SClément Léger 	if (!cell->ops->read_cell)
66*515c1ba9SClément Léger 		return TEE_ERROR_NOT_SUPPORTED;
67*515c1ba9SClément Léger 
68*515c1ba9SClément Léger 	*out_data = malloc(cell->len);
69*515c1ba9SClément Léger 	if (!out_data)
70*515c1ba9SClément Léger 		return TEE_ERROR_OUT_OF_MEMORY;
71*515c1ba9SClément Léger 
72*515c1ba9SClément Léger 	res = cell->ops->read_cell(cell, *out_data);
73*515c1ba9SClément Léger 	if (res)
74*515c1ba9SClément Léger 		free(*out_data);
75*515c1ba9SClément Léger 
76*515c1ba9SClément Léger 	return res;
77*515c1ba9SClément Léger }
78