// SPDX-License-Identifier: GPL-2.0
/*
* nvmem framework core.
*
* Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
* Copyright (C) 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
*/
#include <linux/device.h>
#include <linux/export.h>
#include <linux/fs.h>
#include <linux/idr.h>
#include <linux/init.h>
#include <linux/kref.h>
#include <linux/module.h>
#include <linux/nvmem-consumer.h>
#include <linux/nvmem-provider.h>
#include <linux/of.h>
#include <linux/slab.h>
#include "nvmem.h"
struct nvmem_cell {
const char *name;
int offset;
int bytes;
int bit_offset;
int nbits;
struct device_node *np;
struct nvmem_device *nvmem;
struct list_head node;
};
static DEFINE_MUTEX(nvmem_mutex);
static DEFINE_IDA(nvmem_ida);
static DEFINE_MUTEX(nvmem_cell_mutex);
static LIST_HEAD(nvmem_cell_tables);
static DEFINE_MUTEX(nvmem_lookup_mutex);
static LIST_HEAD(nvmem_lookup_list);
static BLOCKING_NOTIFIER_HEAD(nvmem_notifier);
static int nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset,
void *val, size_t bytes)
{
if (nvmem->reg_read)
return nvmem->reg_read(nvmem->priv, offset, val, bytes);
return -EINVAL;
}
static int nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset,
void *val, size_t bytes)
{
if (nvmem->reg_write)
return nvmem->reg_write(nvmem->priv, offset, val, bytes);
return -EINVAL;
}
static void nvmem_release(struct device *dev)
{
struct nvmem_device *nvmem = to_nvmem_device(dev);
ida_simple_remove(&nvmem_ida, nvmem->id);
kfree(nvmem);
}
static const struct device_type nvmem_provider_type = {
.release = nvmem_release,
};
static struct bus_type nvmem_bus_type = {
.name = "nvmem",
};
static int of_nvmem_match(struct device *dev, const void *nvmem_np)
{
return dev->of_node == nvmem_np;
}
static struct nvmem_device *of_nvmem_find(struct device_node *nvmem_np)
{
struct device *d;