From: Shiraz Hashim <shashim@xxxxxxxxxxxxxx> 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. Signed-off-by: Shiraz Hashim <shashim@xxxxxxxxxxxxxx> Signed-off-by: Gaurav Kohli <gkohli@xxxxxxxxxxxxxx> Co-developed-by: Gaurav Kohli <gkohli@xxxxxxxxxxxxxx> diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index f24008b..e4b6160 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -47,6 +47,7 @@ struct nvmem_cell { int nbits; struct device_node *np; struct nvmem_device *nvmem; + struct bin_attribute attr; struct list_head node; }; @@ -99,6 +100,27 @@ static ssize_t type_show(struct device *dev, return sprintf(buf, "%s\n", nvmem_type_str[nvmem->type]); } +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; + + if (attr->private) + cell = attr->private; + else + return -EINVAL; + + data = nvmem_cell_read(cell, &len); + + len = (len > count) ? count : len; + memcpy(buf, data, len); + + return len; +} + static DEVICE_ATTR_RO(type); static struct attribute *nvmem_attrs[] = { @@ -324,6 +346,7 @@ static void nvmem_cell_drop(struct nvmem_cell *cell) { blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_REMOVE, cell); mutex_lock(&nvmem_mutex); + device_remove_bin_file(&cell->nvmem->dev, &cell->attr); list_del(&cell->node); mutex_unlock(&nvmem_mutex); of_node_put(cell->np); @@ -341,8 +364,24 @@ static void nvmem_device_remove_all_cells(const struct nvmem_device *nvmem) static void nvmem_cell_add(struct nvmem_cell *cell) { + int rval; + struct bin_attribute *nvmem_cell_attr = &cell->attr; + mutex_lock(&nvmem_mutex); list_add_tail(&cell->node, &cell->nvmem->cells); + + /* add attr for this cell */ + nvmem_cell_attr->attr.name = cell->name; + nvmem_cell_attr->attr.mode = 0400; + 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); + } + mutex_unlock(&nvmem_mutex); blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_ADD, cell); } -- Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.