1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * Copyright (c) 2022 Sean Anderson <sean.anderson@seco.com>
4 */
5
6#ifndef NVMEM_H
7#define NVMEM_H
8
9#include <linux/errno.h>
10
11/**
12 * DOC: Design
13 *
14 * The NVMEM subsystem is a "meta-uclass" in that it abstracts over several
15 * different uclasses all with read/write APIs. One approach to implementing
16 * this could be to add a new sub-device for each nvmem-style device of
17 * UCLASS_NVMEM. This subsystem has taken the approach of using the existing
18 * access methods (i2c_eeprom_write, misc_write, etc.) directly. This has the
19 * advantage of not requiring an extra device/driver, saving on binary size and
20 * runtime memory usage. On the other hand, it is not idiomatic. Similar
21 * efforts should generally use a new uclass.
22 */
23
24/**
25 * struct nvmem_cell - One datum within non-volatile memory
26 * @nvmem: The backing storage device
27 * @offset: The offset of the cell from the start of @nvmem
28 * @size: The size of the cell, in bytes
29 */
30struct nvmem_cell {
31	struct udevice *nvmem;
32	unsigned int offset;
33	size_t size;
34};
35
36struct udevice;
37
38#if CONFIG_IS_ENABLED(NVMEM)
39
40/**
41 * nvmem_cell_read() - Read the value of an nvmem cell
42 * @cell: The nvmem cell to read
43 * @buf: The buffer to read into
44 * @size: The size of @buf
45 *
46 * Return:
47 * * 0 on success
48 * * -EINVAL if @buf is not the same size as @cell.
49 * * -ENOSYS if CONFIG_NVMEM is disabled
50 * * A negative error if there was a problem reading the underlying storage
51 */
52int nvmem_cell_read(struct nvmem_cell *cell, void *buf, size_t size);
53
54/**
55 * nvmem_cell_write() - Write a value to an nvmem cell
56 * @cell: The nvmem cell to write
57 * @buf: The buffer to write from
58 * @size: The size of @buf
59 *
60 * Return:
61 * * 0 on success
62 * * -EINVAL if @buf is not the same size as @cell
63 * * -ENOSYS if @cell is read-only, or if CONFIG_NVMEM is disabled
64 * * A negative error if there was a problem writing the underlying storage
65 */
66int nvmem_cell_write(struct nvmem_cell *cell, const void *buf, size_t size);
67
68/**
69 * nvmem_cell_get_by_index() - Get an nvmem cell from a given device and index
70 * @dev: The device that uses the nvmem cell
71 * @index: The index of the cell in nvmem-cells
72 * @cell: The cell to initialize
73 *
74 * Look up the nvmem cell referenced by the phandle at @index in nvmem-cells in
75 * @dev.
76 *
77 * Return:
78 * * 0 on success
79 * * -EINVAL if the regs property is missing, empty, or undersized
80 * * -ENODEV if the nvmem device is missing or unimplemented
81 * * -ENOSYS if CONFIG_NVMEM is disabled
82 * * A negative error if there was a problem reading nvmem-cells or getting the
83 *   device
84 */
85int nvmem_cell_get_by_index(struct udevice *dev, int index,
86			    struct nvmem_cell *cell);
87
88/**
89 * nvmem_cell_get_by_name() - Get an nvmem cell from a given device and name
90 * @dev: The device that uses the nvmem cell
91 * @name: The name of the nvmem cell
92 * @cell: The cell to initialize
93 *
94 * Look up the nvmem cell referenced by @name in the nvmem-cell-names property
95 * of @dev.
96 *
97 * Return:
98 * * 0 on success
99 * * -EINVAL if the regs property is missing, empty, or undersized
100 * * -ENODEV if the nvmem device is missing or unimplemented
101 * * -ENODATA if @name is not in nvmem-cell-names
102 * * -ENOSYS if CONFIG_NVMEM is disabled
103 * * A negative error if there was a problem reading nvmem-cell-names,
104 *   nvmem-cells, or getting the device
105 */
106int nvmem_cell_get_by_name(struct udevice *dev, const char *name,
107			   struct nvmem_cell *cell);
108
109#else /* CONFIG_NVMEM */
110
111static inline int nvmem_cell_read(struct nvmem_cell *cell, void *buf, int size)
112{
113	return -ENOSYS;
114}
115
116static inline int nvmem_cell_write(struct nvmem_cell *cell, const void *buf,
117				   int size)
118{
119	return -ENOSYS;
120}
121
122static inline int nvmem_cell_get_by_index(struct udevice *dev, int index,
123					  struct nvmem_cell *cell)
124{
125	return -ENOSYS;
126}
127
128static inline int nvmem_cell_get_by_name(struct udevice *dev, const char *name,
129					 struct nvmem_cell *cell)
130{
131	return -ENOSYS;
132}
133
134#endif /* CONFIG_NVMEM */
135
136#endif /* NVMEM_H */
137