summaryrefslogtreecommitdiffstats
path: root/drivers/nvmem/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/nvmem/core.c')
-rw-r--r--drivers/nvmem/core.c41
1 files changed, 36 insertions, 5 deletions
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 9b18ce90f907..f7301bb4ef3b 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -28,6 +28,7 @@ struct nvmem_device {
size_t size;
bool read_only;
int flags;
+ enum nvmem_type type;
struct bin_attribute eeprom;
struct device *base_dev;
struct list_head cells;
@@ -44,6 +45,7 @@ struct nvmem_cell {
int bytes;
int bit_offset;
int nbits;
+ struct device_node *np;
struct nvmem_device *nvmem;
struct list_head node;
};
@@ -59,6 +61,13 @@ static LIST_HEAD(nvmem_lookup_list);
static BLOCKING_NOTIFIER_HEAD(nvmem_notifier);
+static const char * const nvmem_type_str[] = {
+ [NVMEM_TYPE_UNKNOWN] = "Unknown",
+ [NVMEM_TYPE_EEPROM] = "EEPROM",
+ [NVMEM_TYPE_OTP] = "OTP",
+ [NVMEM_TYPE_BATTERY_BACKED] = "Battery backed",
+};
+
#ifdef CONFIG_DEBUG_LOCK_ALLOC
static struct lock_class_key eeprom_lock_key;
#endif
@@ -82,6 +91,21 @@ static int nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset,
return -EINVAL;
}
+static ssize_t type_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct nvmem_device *nvmem = to_nvmem_device(dev);
+
+ return sprintf(buf, "%s\n", nvmem_type_str[nvmem->type]);
+}
+
+static DEVICE_ATTR_RO(type);
+
+static struct attribute *nvmem_attrs[] = {
+ &dev_attr_type.attr,
+ NULL,
+};
+
static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr,
char *buf, loff_t pos, size_t count)
@@ -167,6 +191,7 @@ static struct bin_attribute *nvmem_bin_rw_attributes[] = {
static const struct attribute_group nvmem_bin_rw_group = {
.bin_attrs = nvmem_bin_rw_attributes,
+ .attrs = nvmem_attrs,
};
static const struct attribute_group *nvmem_rw_dev_groups[] = {
@@ -190,6 +215,7 @@ static struct bin_attribute *nvmem_bin_ro_attributes[] = {
static const struct attribute_group nvmem_bin_ro_group = {
.bin_attrs = nvmem_bin_ro_attributes,
+ .attrs = nvmem_attrs,
};
static const struct attribute_group *nvmem_ro_dev_groups[] = {
@@ -214,6 +240,7 @@ static struct bin_attribute *nvmem_bin_rw_root_attributes[] = {
static const struct attribute_group nvmem_bin_rw_root_group = {
.bin_attrs = nvmem_bin_rw_root_attributes,
+ .attrs = nvmem_attrs,
};
static const struct attribute_group *nvmem_rw_root_dev_groups[] = {
@@ -237,6 +264,7 @@ static struct bin_attribute *nvmem_bin_ro_root_attributes[] = {
static const struct attribute_group nvmem_bin_ro_root_group = {
.bin_attrs = nvmem_bin_ro_root_attributes,
+ .attrs = nvmem_attrs,
};
static const struct attribute_group *nvmem_ro_root_dev_groups[] = {
@@ -298,6 +326,7 @@ static void nvmem_cell_drop(struct nvmem_cell *cell)
mutex_lock(&nvmem_mutex);
list_del(&cell->node);
mutex_unlock(&nvmem_mutex);
+ of_node_put(cell->np);
kfree(cell->name);
kfree(cell);
}
@@ -530,6 +559,7 @@ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
return -ENOMEM;
cell->nvmem = nvmem;
+ cell->np = of_node_get(child);
cell->offset = be32_to_cpup(addr++);
cell->bytes = be32_to_cpup(addr);
cell->name = kasprintf(GFP_KERNEL, "%pOFn", child);
@@ -602,9 +632,11 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
nvmem->dev.bus = &nvmem_bus_type;
nvmem->dev.parent = config->dev;
nvmem->priv = config->priv;
+ nvmem->type = config->type;
nvmem->reg_read = config->reg_read;
nvmem->reg_write = config->reg_write;
- nvmem->dev.of_node = config->dev->of_node;
+ if (!config->no_of_node)
+ nvmem->dev.of_node = config->dev->of_node;
if (config->id == -1 && config->name) {
dev_set_name(&nvmem->dev, "%s", config->name);
@@ -960,14 +992,13 @@ out:
#if IS_ENABLED(CONFIG_OF)
static struct nvmem_cell *
-nvmem_find_cell_by_index(struct nvmem_device *nvmem, int index)
+nvmem_find_cell_by_node(struct nvmem_device *nvmem, struct device_node *np)
{
struct nvmem_cell *cell = NULL;
- int i = 0;
mutex_lock(&nvmem_mutex);
list_for_each_entry(cell, &nvmem->cells, node) {
- if (index == i++)
+ if (np == cell->np)
break;
}
mutex_unlock(&nvmem_mutex);
@@ -1011,7 +1042,7 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, const char *id)
if (IS_ERR(nvmem))
return ERR_CAST(nvmem);
- cell = nvmem_find_cell_by_index(nvmem, index);
+ cell = nvmem_find_cell_by_node(nvmem, cell_np);
if (!cell) {
__nvmem_device_put(nvmem);
return ERR_PTR(-ENOENT);
OpenPOWER on IntegriCloud