1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2019, Linaro Limited
7 static const char * const nvmem_type_str[] = {
8 [NVMEM_TYPE_UNKNOWN] = "Unknown",
9 [NVMEM_TYPE_EEPROM] = "EEPROM",
10 [NVMEM_TYPE_OTP] = "OTP",
11 [NVMEM_TYPE_BATTERY_BACKED] = "Battery backed",
14 #ifdef CONFIG_DEBUG_LOCK_ALLOC
15 static struct lock_class_key eeprom_lock_key;
18 static ssize_t type_show(struct device *dev,
19 struct device_attribute *attr, char *buf)
21 struct nvmem_device *nvmem = to_nvmem_device(dev);
23 return sprintf(buf, "%s\n", nvmem_type_str[nvmem->type]);
26 static DEVICE_ATTR_RO(type);
28 static struct attribute *nvmem_attrs[] = {
33 static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
34 struct bin_attribute *attr,
35 char *buf, loff_t pos, size_t count)
38 struct nvmem_device *nvmem;
44 dev = container_of(kobj, struct device, kobj);
45 nvmem = to_nvmem_device(dev);
47 /* Stop the user from reading */
48 if (pos >= nvmem->size)
51 if (count < nvmem->word_size)
54 if (pos + count > nvmem->size)
55 count = nvmem->size - pos;
57 count = round_down(count, nvmem->word_size);
62 rc = nvmem->reg_read(nvmem->priv, pos, buf, count);
70 static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
71 struct bin_attribute *attr,
72 char *buf, loff_t pos, size_t count)
75 struct nvmem_device *nvmem;
81 dev = container_of(kobj, struct device, kobj);
82 nvmem = to_nvmem_device(dev);
84 /* Stop the user from writing */
85 if (pos >= nvmem->size)
88 if (count < nvmem->word_size)
91 if (pos + count > nvmem->size)
92 count = nvmem->size - pos;
94 count = round_down(count, nvmem->word_size);
96 if (!nvmem->reg_write)
99 rc = nvmem->reg_write(nvmem->priv, pos, buf, count);
107 /* default read/write permissions */
108 static struct bin_attribute bin_attr_rw_nvmem = {
113 .read = bin_attr_nvmem_read,
114 .write = bin_attr_nvmem_write,
117 static struct bin_attribute *nvmem_bin_rw_attributes[] = {
122 static const struct attribute_group nvmem_bin_rw_group = {
123 .bin_attrs = nvmem_bin_rw_attributes,
124 .attrs = nvmem_attrs,
127 static const struct attribute_group *nvmem_rw_dev_groups[] = {
132 /* read only permission */
133 static struct bin_attribute bin_attr_ro_nvmem = {
138 .read = bin_attr_nvmem_read,
141 static struct bin_attribute *nvmem_bin_ro_attributes[] = {
146 static const struct attribute_group nvmem_bin_ro_group = {
147 .bin_attrs = nvmem_bin_ro_attributes,
148 .attrs = nvmem_attrs,
151 static const struct attribute_group *nvmem_ro_dev_groups[] = {
156 /* default read/write permissions, root only */
157 static struct bin_attribute bin_attr_rw_root_nvmem = {
162 .read = bin_attr_nvmem_read,
163 .write = bin_attr_nvmem_write,
166 static struct bin_attribute *nvmem_bin_rw_root_attributes[] = {
167 &bin_attr_rw_root_nvmem,
171 static const struct attribute_group nvmem_bin_rw_root_group = {
172 .bin_attrs = nvmem_bin_rw_root_attributes,
173 .attrs = nvmem_attrs,
176 static const struct attribute_group *nvmem_rw_root_dev_groups[] = {
177 &nvmem_bin_rw_root_group,
181 /* read only permission, root only */
182 static struct bin_attribute bin_attr_ro_root_nvmem = {
187 .read = bin_attr_nvmem_read,
190 static struct bin_attribute *nvmem_bin_ro_root_attributes[] = {
191 &bin_attr_ro_root_nvmem,
195 static const struct attribute_group nvmem_bin_ro_root_group = {
196 .bin_attrs = nvmem_bin_ro_root_attributes,
197 .attrs = nvmem_attrs,
200 static const struct attribute_group *nvmem_ro_root_dev_groups[] = {
201 &nvmem_bin_ro_root_group,
205 const struct attribute_group **nvmem_sysfs_get_groups(
206 struct nvmem_device *nvmem,
207 const struct nvmem_config *config)
209 if (config->root_only)
210 return nvmem->read_only ?
211 nvmem_ro_root_dev_groups :
212 nvmem_rw_root_dev_groups;
214 return nvmem->read_only ? nvmem_ro_dev_groups : nvmem_rw_dev_groups;
218 * nvmem_setup_compat() - Create an additional binary entry in
219 * drivers sys directory, to be backwards compatible with the older
220 * drivers/misc/eeprom drivers.
222 int nvmem_sysfs_setup_compat(struct nvmem_device *nvmem,
223 const struct nvmem_config *config)
230 if (!config->base_dev)
233 if (nvmem->read_only) {
234 if (config->root_only)
235 nvmem->eeprom = bin_attr_ro_root_nvmem;
237 nvmem->eeprom = bin_attr_ro_nvmem;
239 if (config->root_only)
240 nvmem->eeprom = bin_attr_rw_root_nvmem;
242 nvmem->eeprom = bin_attr_rw_nvmem;
244 nvmem->eeprom.attr.name = "eeprom";
245 nvmem->eeprom.size = nvmem->size;
246 #ifdef CONFIG_DEBUG_LOCK_ALLOC
247 nvmem->eeprom.attr.key = &eeprom_lock_key;
249 nvmem->eeprom.private = &nvmem->dev;
250 nvmem->base_dev = config->base_dev;
252 rval = device_create_bin_file(nvmem->base_dev, &nvmem->eeprom);
255 "Failed to create eeprom binary file %d\n", rval);
259 nvmem->flags |= FLAG_COMPAT;
264 void nvmem_sysfs_remove_compat(struct nvmem_device *nvmem,
265 const struct nvmem_config *config)
268 device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);