diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig index dcaafaee68e4..90fa702867ad 100644 --- a/drivers/nvmem/Kconfig +++ b/drivers/nvmem/Kconfig @@ -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 diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 960542dea5ad..64cffe141075 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -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); }