diff options
author | Bartosz Golaszewski <bgolaszewski@baylibre.com> | 2018-09-21 06:40:15 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-09-28 15:14:54 +0200 |
commit | b985f4cba6dbb3b60ad119c6f7e5cbad6f0d7e45 (patch) | |
tree | 6062e9d3fb702b0cbc496f8a8e2003f7696638fd /drivers/nvmem/core.c | |
parent | c7235ee3f4b86a01507a12e96a4875ba9b4be842 (diff) |
nvmem: add support for cell info
Add new structs and routines allowing users to define nvmem cells from
machine code. This global list of entries is parsed when a provider
is registered and cells are associated with the relevant nvmem_device
struct.
A possible improvement for the future is to allow users to register
cell tables after the nvmem provider has been registered by updating
the cell list at each call to nvmem_(add|del)_cell_table().
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/nvmem/core.c')
-rw-r--r-- | drivers/nvmem/core.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index ee794613024c..8e0108806e65 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -59,6 +59,9 @@ struct nvmem_cell { static DEFINE_MUTEX(nvmem_mutex); static DEFINE_IDA(nvmem_ida); +static DEFINE_MUTEX(nvmem_cell_mutex); +static LIST_HEAD(nvmem_cell_tables); + #ifdef CONFIG_DEBUG_LOCK_ALLOC static struct lock_class_key eeprom_lock_key; #endif @@ -416,6 +419,43 @@ static int nvmem_setup_compat(struct nvmem_device *nvmem, return 0; } +static int nvmem_add_cells_from_table(struct nvmem_device *nvmem) +{ + const struct nvmem_cell_info *info; + struct nvmem_cell_table *table; + struct nvmem_cell *cell; + int rval = 0, i; + + mutex_lock(&nvmem_cell_mutex); + list_for_each_entry(table, &nvmem_cell_tables, node) { + if (strcmp(nvmem_dev_name(nvmem), table->nvmem_name) == 0) { + for (i = 0; i < table->ncells; i++) { + info = &table->cells[i]; + + cell = kzalloc(sizeof(*cell), GFP_KERNEL); + if (!cell) { + rval = -ENOMEM; + goto out; + } + + rval = nvmem_cell_info_to_nvmem_cell(nvmem, + info, + cell); + if (rval) { + kfree(cell); + goto out; + } + + nvmem_cell_add(cell); + } + } + } + +out: + mutex_unlock(&nvmem_cell_mutex); + return rval; +} + /** * nvmem_register() - Register a nvmem device for given nvmem_config. * Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem @@ -502,8 +542,14 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) goto err_teardown_compat; } + rval = nvmem_add_cells_from_table(nvmem); + if (rval) + goto err_remove_cells; + return nvmem; +err_remove_cells: + nvmem_device_remove_all_cells(nvmem); err_teardown_compat: if (config->compat) device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom); @@ -1307,6 +1353,32 @@ int nvmem_device_write(struct nvmem_device *nvmem, EXPORT_SYMBOL_GPL(nvmem_device_write); /** + * nvmem_add_cell_table() - register a table of cell info entries + * + * @table: table of cell info entries + */ +void nvmem_add_cell_table(struct nvmem_cell_table *table) +{ + mutex_lock(&nvmem_cell_mutex); + list_add_tail(&table->node, &nvmem_cell_tables); + mutex_unlock(&nvmem_cell_mutex); +} +EXPORT_SYMBOL_GPL(nvmem_add_cell_table); + +/** + * nvmem_del_cell_table() - remove a previously registered cell info table + * + * @table: table of cell info entries + */ +void nvmem_del_cell_table(struct nvmem_cell_table *table) +{ + mutex_lock(&nvmem_cell_mutex); + list_del(&table->node); + mutex_unlock(&nvmem_cell_mutex); +} +EXPORT_SYMBOL_GPL(nvmem_del_cell_table); + +/** * nvmem_dev_name() - Get the name of a given nvmem device. * * @nvmem: nvmem device. |