summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2022-06-09 15:20:11 -0400
committerTom Rini <[email protected]>2022-06-09 15:20:11 -0400
commite5028bb227c578ca89273f0b1e0d289ec1987d2f (patch)
treea9b8552bc82bd10d9b0638113c2ed65b87a892d7 /include
parentc0e63bf46848d573b3ef86d5796f8f993c316ed6 (diff)
parent3f51ba926bc138f54dab8d0fa0c363a3b1e71794 (diff)
Merge branch '2022-06-09-add-support-for-nvmem-api' into next
To quote the author: This adds support for the nvmem-cells properties cropping up in manyb device trees. This is an easy way to load configuration, version information, or calibration data from a non-volatile memory source. For more information, refer to patch 6 ("misc: Add support for nvmem cells"). For the moment I have only added some integration tests using the ethernet addresses. This hits the main code paths (looking up nvmem cells) but doesn't test writing. I can add a few stand-alone tests if desired.
Diffstat (limited to 'include')
-rw-r--r--include/i2c_eeprom.h27
-rw-r--r--include/nvmem.h134
2 files changed, 160 insertions, 1 deletions
diff --git a/include/i2c_eeprom.h b/include/i2c_eeprom.h
index 3ad565684fe..32dcb034973 100644
--- a/include/i2c_eeprom.h
+++ b/include/i2c_eeprom.h
@@ -6,6 +6,8 @@
#ifndef __I2C_EEPROM
#define __I2C_EEPROM
+struct udevice;
+
struct i2c_eeprom_ops {
int (*read)(struct udevice *dev, int offset, uint8_t *buf, int size);
int (*write)(struct udevice *dev, int offset, const uint8_t *buf,
@@ -20,6 +22,7 @@ struct i2c_eeprom {
unsigned long size;
};
+#if CONFIG_IS_ENABLED(I2C_EEPROM)
/*
* i2c_eeprom_read() - read bytes from an I2C EEPROM chip
*
@@ -42,7 +45,8 @@ int i2c_eeprom_read(struct udevice *dev, int offset, uint8_t *buf, int size);
*
* Return: 0 on success, -ve on failure
*/
-int i2c_eeprom_write(struct udevice *dev, int offset, uint8_t *buf, int size);
+int i2c_eeprom_write(struct udevice *dev, int offset, const uint8_t *buf,
+ int size);
/*
* i2c_eeprom_size() - get size of I2C EEPROM chip
@@ -53,4 +57,25 @@ int i2c_eeprom_write(struct udevice *dev, int offset, uint8_t *buf, int size);
*/
int i2c_eeprom_size(struct udevice *dev);
+#else /* !I2C_EEPROM */
+
+static inline int i2c_eeprom_read(struct udevice *dev, int offset, uint8_t *buf,
+ int size)
+{
+ return -ENOSYS;
+}
+
+static inline int i2c_eeprom_write(struct udevice *dev, int offset,
+ const uint8_t *buf, int size)
+{
+ return -ENOSYS;
+}
+
+static inline int i2c_eeprom_size(struct udevice *dev)
+{
+ return -ENOSYS;
+}
+
+#endif /* I2C_EEPROM */
+
#endif
diff --git a/include/nvmem.h b/include/nvmem.h
new file mode 100644
index 00000000000..822e698bdd4
--- /dev/null
+++ b/include/nvmem.h
@@ -0,0 +1,134 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2022 Sean Anderson <[email protected]>
+ */
+
+#ifndef NVMEM_H
+#define NVMEM_H
+
+/**
+ * DOC: Design
+ *
+ * The NVMEM subsystem is a "meta-uclass" in that it abstracts over several
+ * different uclasses all with read/write APIs. One approach to implementing
+ * this could be to add a new sub-device for each nvmem-style device of
+ * UCLASS_NVMEM. This subsystem has taken the approach of using the existing
+ * access methods (i2c_eeprom_write, misc_write, etc.) directly. This has the
+ * advantage of not requiring an extra device/driver, saving on binary size and
+ * runtime memory usage. On the other hand, it is not idiomatic. Similar
+ * efforts should generally use a new uclass.
+ */
+
+/**
+ * struct nvmem_cell - One datum within non-volatile memory
+ * @nvmem: The backing storage device
+ * @offset: The offset of the cell from the start of @nvmem
+ * @size: The size of the cell, in bytes
+ */
+struct nvmem_cell {
+ struct udevice *nvmem;
+ unsigned int offset;
+ size_t size;
+};
+
+struct udevice;
+
+#if CONFIG_IS_ENABLED(NVMEM)
+
+/**
+ * nvmem_cell_read() - Read the value of an nvmem cell
+ * @cell: The nvmem cell to read
+ * @buf: The buffer to read into
+ * @size: The size of @buf
+ *
+ * Return:
+ * * 0 on success
+ * * -EINVAL if @buf is not the same size as @cell.
+ * * -ENOSYS if CONFIG_NVMEM is disabled
+ * * A negative error if there was a problem reading the underlying storage
+ */
+int nvmem_cell_read(struct nvmem_cell *cell, void *buf, size_t size);
+
+/**
+ * nvmem_cell_write() - Write a value to an nvmem cell
+ * @cell: The nvmem cell to write
+ * @buf: The buffer to write from
+ * @size: The size of @buf
+ *
+ * Return:
+ * * 0 on success
+ * * -EINVAL if @buf is not the same size as @cell
+ * * -ENOSYS if @cell is read-only, or if CONFIG_NVMEM is disabled
+ * * A negative error if there was a problem writing the underlying storage
+ */
+int nvmem_cell_write(struct nvmem_cell *cell, const void *buf, size_t size);
+
+/**
+ * nvmem_cell_get_by_index() - Get an nvmem cell from a given device and index
+ * @dev: The device that uses the nvmem cell
+ * @index: The index of the cell in nvmem-cells
+ * @cell: The cell to initialize
+ *
+ * Look up the nvmem cell referenced by the phandle at @index in nvmem-cells in
+ * @dev.
+ *
+ * Return:
+ * * 0 on success
+ * * -EINVAL if the regs property is missing, empty, or undersized
+ * * -ENODEV if the nvmem device is missing or unimplemented
+ * * -ENOSYS if CONFIG_NVMEM is disabled
+ * * A negative error if there was a problem reading nvmem-cells or getting the
+ * device
+ */
+int nvmem_cell_get_by_index(struct udevice *dev, int index,
+ struct nvmem_cell *cell);
+
+/**
+ * nvmem_cell_get_by_name() - Get an nvmem cell from a given device and name
+ * @dev: The device that uses the nvmem cell
+ * @name: The name of the nvmem cell
+ * @cell: The cell to initialize
+ *
+ * Look up the nvmem cell referenced by @name in the nvmem-cell-names property
+ * of @dev.
+ *
+ * Return:
+ * * 0 on success
+ * * -EINVAL if the regs property is missing, empty, or undersized
+ * * -ENODEV if the nvmem device is missing or unimplemented
+ * * -ENODATA if @name is not in nvmem-cell-names
+ * * -ENOSYS if CONFIG_NVMEM is disabled
+ * * A negative error if there was a problem reading nvmem-cell-names,
+ * nvmem-cells, or getting the device
+ */
+int nvmem_cell_get_by_name(struct udevice *dev, const char *name,
+ struct nvmem_cell *cell);
+
+#else /* CONFIG_NVMEM */
+
+static inline int nvmem_cell_read(struct nvmem_cell *cell, void *buf, int size)
+{
+ return -ENOSYS;
+}
+
+static inline int nvmem_cell_write(struct nvmem_cell *cell, const void *buf,
+ int size)
+{
+ return -ENOSYS;
+}
+
+static inline int nvmem_cell_get_by_index(struct udevice *dev, int index,
+ struct nvmem_cell *cell)
+{
+ return -ENOSYS;
+}
+
+static inline int nvmem_cell_get_by_name(struct udevice *dev, const char *name,
+ struct nvmem_cell *cell)
+{
+ return -ENOSYS;
+}
+
+#endif /* CONFIG_NVMEM */
+
+#endif /* NVMEM_H */