Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 15d33a02 authored by Shiraz Hashim's avatar Shiraz Hashim Committed by Gerrit - the friendly Code Review server
Browse files

nvmem: core: Export nvmem cell info to userspace



Existing nvmem framework export full register space
as nvmem binary, but not exporting child node of nvmem
which is nvmem cell. Kernel can read the specific cell
by using nvmem_cell_read but userspace don't have such
provision.

Add framework to export nvmem cell as well, So
userspace can use it directly.

Change-Id: I3b41a91820f6d2a4536933e7bab4ac1b94f1541a
Signed-off-by: default avatarShiraz Hashim <shashim@codeaurora.org>
Signed-off-by: default avatarGaurav Kohli <gkohli@codeaurora.org>
parent 53badd7f
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -97,6 +97,13 @@ config MTK_EFUSE
	  This driver can also be built as a module. If so, the module
	  will be called efuse-mtk.

config QCOM_QFPROM_SYSFS
	tristate "QCOM QFPROM SYSFS"
	depends on QCOM_QFPROM
	help
	  Say y here to enable QFPROM SYSFS support. The QFPROM SYSFS
	  create each child node of QFPROM as sysfs entries as well.

config QCOM_QFPROM
	tristate "QCOM QFPROM Support"
	depends on ARCH_QCOM || COMPILE_TEST
+45 −0
Original line number Diff line number Diff line
@@ -27,6 +27,9 @@ struct nvmem_cell {
	int			nbits;
	struct device_node	*np;
	struct nvmem_device	*nvmem;
#ifdef CONFIG_QCOM_QFPROM_SYSFS
	struct bin_attribute	attr;
#endif
	struct list_head	node;
};

@@ -60,6 +63,28 @@ static int nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset,
	return -EINVAL;
}

#ifdef CONFIG_QCOM_QFPROM_SYSFS
static ssize_t bin_attr_nvmem_cell_read(struct file *filp, struct kobject *kobj,
				    struct bin_attribute *attr,
				    char *buf, loff_t pos, size_t count)
{
	struct nvmem_cell *cell;
	size_t len;
	u8 *data;

	cell = attr->private;

	data = nvmem_cell_read(cell, &len);
	if (IS_ERR(data))
		return -EINVAL;

	len = min(len, count);
	memcpy(buf, data, len);
	kfree(data);
	return len;
}
#endif

static void nvmem_release(struct device *dev)
{
	struct nvmem_device *nvmem = to_nvmem_device(dev);
@@ -107,6 +132,9 @@ static void nvmem_cell_drop(struct nvmem_cell *cell)
{
	blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_REMOVE, cell);
	mutex_lock(&nvmem_mutex);
#ifdef CONFIG_QCOM_QFPROM_SYSFS
	device_remove_bin_file(&cell->nvmem->dev, &cell->attr);
#endif
	list_del(&cell->node);
	mutex_unlock(&nvmem_mutex);
	of_node_put(cell->np);
@@ -124,8 +152,25 @@ static void nvmem_device_remove_all_cells(const struct nvmem_device *nvmem)

static void nvmem_cell_add(struct nvmem_cell *cell)
{
#ifdef CONFIG_QCOM_QFPROM_SYSFS
	int rval;
	struct bin_attribute *nvmem_cell_attr = &cell->attr;
#endif
	mutex_lock(&nvmem_mutex);
	list_add_tail(&cell->node, &cell->nvmem->cells);

#ifdef CONFIG_QCOM_QFPROM_SYSFS
	/* add attr for this cell */
	nvmem_cell_attr->attr.name = cell->name;
	nvmem_cell_attr->attr.mode = 0444;
	nvmem_cell_attr->private = cell;
	nvmem_cell_attr->size = cell->bytes;
	nvmem_cell_attr->read = bin_attr_nvmem_cell_read;
	rval = device_create_bin_file(&cell->nvmem->dev, nvmem_cell_attr);
	if (rval)
		dev_err(&cell->nvmem->dev,
			"Failed to create cell binary file %d\n", rval);
#endif
	mutex_unlock(&nvmem_mutex);
	blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_ADD, cell);
}