aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSrinivas Kandagatla <srinivas.kandagatla@linaro.org>2019-04-16 05:59:24 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-04-25 13:44:33 -0400
commitae0c2d725512f32a0d1a25f0cf2f07616d33a72e (patch)
treeefc94c4d7eebd08678b03a27ecd51272da797665
parentfc1eb6ebbd55e20819e8ec5f07a2bf71e3bea5f1 (diff)
nvmem: core: add NVMEM_SYSFS Kconfig
Many nvmem providers are not very keen on having default sysfs nvmem entry, as most of the usecases for them are inside kernel itself. And in some cases read/writes to some areas in nvmem are restricted and trapped at secure monitor level, so accessing them from userspace would result in board reboots. This patch adds new NVMEM_SYSFS Kconfig to make binary sysfs entry an optional one. This provision will give more flexibility to users. This patch also moves existing sysfs code to a new file so that its not compiled in when its not really required. Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com> Reviewed-by: Gaurav Kohli <gkohli@codeaurora.org> Tested-by: Gaurav Kohli <gkohli@codeaurora.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--Documentation/ABI/stable/sysfs-bus-nvmem2
-rw-r--r--drivers/nvmem/Kconfig10
-rw-r--r--drivers/nvmem/Makefile3
-rw-r--r--drivers/nvmem/core.c264
-rw-r--r--drivers/nvmem/nvmem-sysfs.c256
-rw-r--r--drivers/nvmem/nvmem.h62
6 files changed, 337 insertions, 260 deletions
diff --git a/Documentation/ABI/stable/sysfs-bus-nvmem b/Documentation/ABI/stable/sysfs-bus-nvmem
index 5923ab4620c5..9ffba8576f7b 100644
--- a/Documentation/ABI/stable/sysfs-bus-nvmem
+++ b/Documentation/ABI/stable/sysfs-bus-nvmem
@@ -6,6 +6,8 @@ Description:
6 This file allows user to read/write the raw NVMEM contents. 6 This file allows user to read/write the raw NVMEM contents.
7 Permissions for write to this file depends on the nvmem 7 Permissions for write to this file depends on the nvmem
8 provider configuration. 8 provider configuration.
9 Note: This file is only present if CONFIG_NVMEM_SYSFS
10 is enabled
9 11
10 ex: 12 ex:
11 hexdump /sys/bus/nvmem/devices/qfprom0/nvmem 13 hexdump /sys/bus/nvmem/devices/qfprom0/nvmem
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index a90e9a1ebe55..6b2c4254c2fb 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -13,6 +13,16 @@ menuconfig NVMEM
13 13
14if NVMEM 14if NVMEM
15 15
16config NVMEM_SYSFS
17 bool "/sys/bus/nvmem/devices/*/nvmem (sysfs interface)"
18 depends on SYSFS
19 default y
20 help
21 Say Y here to add a sysfs interface for NVMEM.
22
23 This interface is mostly used by userspace applications to
24 read/write directly into nvmem.
25
16config NVMEM_IMX_IIM 26config NVMEM_IMX_IIM
17 tristate "i.MX IC Identification Module support" 27 tristate "i.MX IC Identification Module support"
18 depends on ARCH_MXC || COMPILE_TEST 28 depends on ARCH_MXC || COMPILE_TEST
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 4c7ba12a7005..c1fe4768dfef 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -6,6 +6,9 @@
6obj-$(CONFIG_NVMEM) += nvmem_core.o 6obj-$(CONFIG_NVMEM) += nvmem_core.o
7nvmem_core-y := core.o 7nvmem_core-y := core.o
8 8
9obj-$(CONFIG_NVMEM_SYSFS) += nvmem_sysfs.o
10nvmem_sysfs-y := nvmem-sysfs.o
11
9# Devices 12# Devices
10obj-$(CONFIG_NVMEM_BCM_OCOTP) += nvmem-bcm-ocotp.o 13obj-$(CONFIG_NVMEM_BCM_OCOTP) += nvmem-bcm-ocotp.o
11nvmem-bcm-ocotp-y := bcm-ocotp.o 14nvmem-bcm-ocotp-y := bcm-ocotp.o
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 5abebf2128b8..c7892c3da91f 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -17,27 +17,7 @@
17#include <linux/nvmem-provider.h> 17#include <linux/nvmem-provider.h>
18#include <linux/of.h> 18#include <linux/of.h>
19#include <linux/slab.h> 19#include <linux/slab.h>
20 20#include "nvmem.h"
21struct nvmem_device {
22 struct module *owner;
23 struct device dev;
24 int stride;
25 int word_size;
26 int id;
27 struct kref refcnt;
28 size_t size;
29 bool read_only;
30 int flags;
31 enum nvmem_type type;
32 struct bin_attribute eeprom;
33 struct device *base_dev;
34 struct list_head cells;
35 nvmem_reg_read_t reg_read;
36 nvmem_reg_write_t reg_write;
37 void *priv;
38};
39
40#define FLAG_COMPAT BIT(0)
41 21
42struct nvmem_cell { 22struct nvmem_cell {
43 const char *name; 23 const char *name;
@@ -61,18 +41,7 @@ static LIST_HEAD(nvmem_lookup_list);
61 41
62static BLOCKING_NOTIFIER_HEAD(nvmem_notifier); 42static BLOCKING_NOTIFIER_HEAD(nvmem_notifier);
63 43
64static const char * const nvmem_type_str[] = {
65 [NVMEM_TYPE_UNKNOWN] = "Unknown",
66 [NVMEM_TYPE_EEPROM] = "EEPROM",
67 [NVMEM_TYPE_OTP] = "OTP",
68 [NVMEM_TYPE_BATTERY_BACKED] = "Battery backed",
69};
70
71#ifdef CONFIG_DEBUG_LOCK_ALLOC
72static struct lock_class_key eeprom_lock_key;
73#endif
74 44
75#define to_nvmem_device(d) container_of(d, struct nvmem_device, dev)
76static int nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset, 45static int nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset,
77 void *val, size_t bytes) 46 void *val, size_t bytes)
78{ 47{
@@ -91,187 +60,6 @@ static int nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset,
91 return -EINVAL; 60 return -EINVAL;
92} 61}
93 62
94static ssize_t type_show(struct device *dev,
95 struct device_attribute *attr, char *buf)
96{
97 struct nvmem_device *nvmem = to_nvmem_device(dev);
98
99 return sprintf(buf, "%s\n", nvmem_type_str[nvmem->type]);
100}
101
102static DEVICE_ATTR_RO(type);
103
104static struct attribute *nvmem_attrs[] = {
105 &dev_attr_type.attr,
106 NULL,
107};
108
109static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
110 struct bin_attribute *attr,
111 char *buf, loff_t pos, size_t count)
112{
113 struct device *dev;
114 struct nvmem_device *nvmem;
115 int rc;
116
117 if (attr->private)
118 dev = attr->private;
119 else
120 dev = container_of(kobj, struct device, kobj);
121 nvmem = to_nvmem_device(dev);
122
123 /* Stop the user from reading */
124 if (pos >= nvmem->size)
125 return 0;
126
127 if (count < nvmem->word_size)
128 return -EINVAL;
129
130 if (pos + count > nvmem->size)
131 count = nvmem->size - pos;
132
133 count = round_down(count, nvmem->word_size);
134
135 rc = nvmem_reg_read(nvmem, pos, buf, count);
136
137 if (rc)
138 return rc;
139
140 return count;
141}
142
143static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
144 struct bin_attribute *attr,
145 char *buf, loff_t pos, size_t count)
146{
147 struct device *dev;
148 struct nvmem_device *nvmem;
149 int rc;
150
151 if (attr->private)
152 dev = attr->private;
153 else
154 dev = container_of(kobj, struct device, kobj);
155 nvmem = to_nvmem_device(dev);
156
157 /* Stop the user from writing */
158 if (pos >= nvmem->size)
159 return -EFBIG;
160
161 if (count < nvmem->word_size)
162 return -EINVAL;
163
164 if (pos + count > nvmem->size)
165 count = nvmem->size - pos;
166
167 count = round_down(count, nvmem->word_size);
168
169 rc = nvmem_reg_write(nvmem, pos, buf, count);
170
171 if (rc)
172 return rc;
173
174 return count;
175}
176
177/* default read/write permissions */
178static struct bin_attribute bin_attr_rw_nvmem = {
179 .attr = {
180 .name = "nvmem",
181 .mode = 0644,
182 },
183 .read = bin_attr_nvmem_read,
184 .write = bin_attr_nvmem_write,
185};
186
187static struct bin_attribute *nvmem_bin_rw_attributes[] = {
188 &bin_attr_rw_nvmem,
189 NULL,
190};
191
192static const struct attribute_group nvmem_bin_rw_group = {
193 .bin_attrs = nvmem_bin_rw_attributes,
194 .attrs = nvmem_attrs,
195};
196
197static const struct attribute_group *nvmem_rw_dev_groups[] = {
198 &nvmem_bin_rw_group,
199 NULL,
200};
201
202/* read only permission */
203static struct bin_attribute bin_attr_ro_nvmem = {
204 .attr = {
205 .name = "nvmem",
206 .mode = 0444,
207 },
208 .read = bin_attr_nvmem_read,
209};
210
211static struct bin_attribute *nvmem_bin_ro_attributes[] = {
212 &bin_attr_ro_nvmem,
213 NULL,
214};
215
216static const struct attribute_group nvmem_bin_ro_group = {
217 .bin_attrs = nvmem_bin_ro_attributes,
218 .attrs = nvmem_attrs,
219};
220
221static const struct attribute_group *nvmem_ro_dev_groups[] = {
222 &nvmem_bin_ro_group,
223 NULL,
224};
225
226/* default read/write permissions, root only */
227static struct bin_attribute bin_attr_rw_root_nvmem = {
228 .attr = {
229 .name = "nvmem",
230 .mode = 0600,
231 },
232 .read = bin_attr_nvmem_read,
233 .write = bin_attr_nvmem_write,
234};
235
236static struct bin_attribute *nvmem_bin_rw_root_attributes[] = {
237 &bin_attr_rw_root_nvmem,
238 NULL,
239};
240
241static const struct attribute_group nvmem_bin_rw_root_group = {
242 .bin_attrs = nvmem_bin_rw_root_attributes,
243 .attrs = nvmem_attrs,
244};
245
246static const struct attribute_group *nvmem_rw_root_dev_groups[] = {
247 &nvmem_bin_rw_root_group,
248 NULL,
249};
250
251/* read only permission, root only */
252static struct bin_attribute bin_attr_ro_root_nvmem = {
253 .attr = {
254 .name = "nvmem",
255 .mode = 0400,
256 },
257 .read = bin_attr_nvmem_read,
258};
259
260static struct bin_attribute *nvmem_bin_ro_root_attributes[] = {
261 &bin_attr_ro_root_nvmem,
262 NULL,
263};
264
265static const struct attribute_group nvmem_bin_ro_root_group = {
266 .bin_attrs = nvmem_bin_ro_root_attributes,
267 .attrs = nvmem_attrs,
268};
269
270static const struct attribute_group *nvmem_ro_root_dev_groups[] = {
271 &nvmem_bin_ro_root_group,
272 NULL,
273};
274
275static void nvmem_release(struct device *dev) 63static void nvmem_release(struct device *dev)
276{ 64{
277 struct nvmem_device *nvmem = to_nvmem_device(dev); 65 struct nvmem_device *nvmem = to_nvmem_device(dev);
@@ -422,43 +210,6 @@ err:
422 return rval; 210 return rval;
423} 211}
424 212
425/*
426 * nvmem_setup_compat() - Create an additional binary entry in
427 * drivers sys directory, to be backwards compatible with the older
428 * drivers/misc/eeprom drivers.
429 */
430static int nvmem_setup_compat(struct nvmem_device *nvmem,
431 const struct nvmem_config *config)
432{
433 int rval;
434
435 if (!config->base_dev)
436 return -EINVAL;
437
438 if (nvmem->read_only)
439 nvmem->eeprom = bin_attr_ro_root_nvmem;
440 else
441 nvmem->eeprom = bin_attr_rw_root_nvmem;
442 nvmem->eeprom.attr.name = "eeprom";
443 nvmem->eeprom.size = nvmem->size;
444#ifdef CONFIG_DEBUG_LOCK_ALLOC
445 nvmem->eeprom.attr.key = &eeprom_lock_key;
446#endif
447 nvmem->eeprom.private = &nvmem->dev;
448 nvmem->base_dev = config->base_dev;
449
450 rval = device_create_bin_file(nvmem->base_dev, &nvmem->eeprom);
451 if (rval) {
452 dev_err(&nvmem->dev,
453 "Failed to create eeprom binary file %d\n", rval);
454 return rval;
455 }
456
457 nvmem->flags |= FLAG_COMPAT;
458
459 return 0;
460}
461
462/** 213/**
463 * nvmem_register_notifier() - Register a notifier block for nvmem events. 214 * nvmem_register_notifier() - Register a notifier block for nvmem events.
464 * 215 *
@@ -651,14 +402,7 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
651 nvmem->read_only = device_property_present(config->dev, "read-only") || 402 nvmem->read_only = device_property_present(config->dev, "read-only") ||
652 config->read_only || !nvmem->reg_write; 403 config->read_only || !nvmem->reg_write;
653 404
654 if (config->root_only) 405 nvmem->dev.groups = nvmem_sysfs_get_groups(nvmem, config);
655 nvmem->dev.groups = nvmem->read_only ?
656 nvmem_ro_root_dev_groups :
657 nvmem_rw_root_dev_groups;
658 else
659 nvmem->dev.groups = nvmem->read_only ?
660 nvmem_ro_dev_groups :
661 nvmem_rw_dev_groups;
662 406
663 device_initialize(&nvmem->dev); 407 device_initialize(&nvmem->dev);
664 408
@@ -669,7 +413,7 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
669 goto err_put_device; 413 goto err_put_device;
670 414
671 if (config->compat) { 415 if (config->compat) {
672 rval = nvmem_setup_compat(nvmem, config); 416 rval = nvmem_sysfs_setup_compat(nvmem, config);
673 if (rval) 417 if (rval)
674 goto err_device_del; 418 goto err_device_del;
675 } 419 }
@@ -696,7 +440,7 @@ err_remove_cells:
696 nvmem_device_remove_all_cells(nvmem); 440 nvmem_device_remove_all_cells(nvmem);
697err_teardown_compat: 441err_teardown_compat:
698 if (config->compat) 442 if (config->compat)
699 device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom); 443 nvmem_sysfs_remove_compat(nvmem, config);
700err_device_del: 444err_device_del:
701 device_del(&nvmem->dev); 445 device_del(&nvmem->dev);
702err_put_device: 446err_put_device:
diff --git a/drivers/nvmem/nvmem-sysfs.c b/drivers/nvmem/nvmem-sysfs.c
new file mode 100644
index 000000000000..6f303b91f6e7
--- /dev/null
+++ b/drivers/nvmem/nvmem-sysfs.c
@@ -0,0 +1,256 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2019, Linaro Limited
4 */
5#include "nvmem.h"
6
7static 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",
12};
13
14#ifdef CONFIG_DEBUG_LOCK_ALLOC
15static struct lock_class_key eeprom_lock_key;
16#endif
17
18static ssize_t type_show(struct device *dev,
19 struct device_attribute *attr, char *buf)
20{
21 struct nvmem_device *nvmem = to_nvmem_device(dev);
22
23 return sprintf(buf, "%s\n", nvmem_type_str[nvmem->type]);
24}
25
26static DEVICE_ATTR_RO(type);
27
28static struct attribute *nvmem_attrs[] = {
29 &dev_attr_type.attr,
30 NULL,
31};
32
33static 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)
36{
37 struct device *dev;
38 struct nvmem_device *nvmem;
39 int rc;
40
41 if (attr->private)
42 dev = attr->private;
43 else
44 dev = container_of(kobj, struct device, kobj);
45 nvmem = to_nvmem_device(dev);
46
47 /* Stop the user from reading */
48 if (pos >= nvmem->size)
49 return 0;
50
51 if (count < nvmem->word_size)
52 return -EINVAL;
53
54 if (pos + count > nvmem->size)
55 count = nvmem->size - pos;
56
57 count = round_down(count, nvmem->word_size);
58
59 rc = nvmem->reg_read(nvmem->priv, pos, buf, count);
60
61 if (rc)
62 return rc;
63
64 return count;
65}
66
67static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
68 struct bin_attribute *attr,
69 char *buf, loff_t pos, size_t count)
70{
71 struct device *dev;
72 struct nvmem_device *nvmem;
73 int rc;
74
75 if (attr->private)
76 dev = attr->private;
77 else
78 dev = container_of(kobj, struct device, kobj);
79 nvmem = to_nvmem_device(dev);
80
81 /* Stop the user from writing */
82 if (pos >= nvmem->size)
83 return -EFBIG;
84
85 if (count < nvmem->word_size)
86 return -EINVAL;
87
88 if (pos + count > nvmem->size)
89 count = nvmem->size - pos;
90
91 count = round_down(count, nvmem->word_size);
92
93 rc = nvmem->reg_write(nvmem->priv, pos, buf, count);
94
95 if (rc)
96 return rc;
97
98 return count;
99}
100
101/* default read/write permissions */
102static struct bin_attribute bin_attr_rw_nvmem = {
103 .attr = {
104 .name = "nvmem",
105 .mode = 0644,
106 },
107 .read = bin_attr_nvmem_read,
108 .write = bin_attr_nvmem_write,
109};
110
111static struct bin_attribute *nvmem_bin_rw_attributes[] = {
112 &bin_attr_rw_nvmem,
113 NULL,
114};
115
116static const struct attribute_group nvmem_bin_rw_group = {
117 .bin_attrs = nvmem_bin_rw_attributes,
118 .attrs = nvmem_attrs,
119};
120
121static const struct attribute_group *nvmem_rw_dev_groups[] = {
122 &nvmem_bin_rw_group,
123 NULL,
124};
125
126/* read only permission */
127static struct bin_attribute bin_attr_ro_nvmem = {
128 .attr = {
129 .name = "nvmem",
130 .mode = 0444,
131 },
132 .read = bin_attr_nvmem_read,
133};
134
135static struct bin_attribute *nvmem_bin_ro_attributes[] = {
136 &bin_attr_ro_nvmem,
137 NULL,
138};
139
140static const struct attribute_group nvmem_bin_ro_group = {
141 .bin_attrs = nvmem_bin_ro_attributes,
142 .attrs = nvmem_attrs,
143};
144
145static const struct attribute_group *nvmem_ro_dev_groups[] = {
146 &nvmem_bin_ro_group,
147 NULL,
148};
149
150/* default read/write permissions, root only */
151static struct bin_attribute bin_attr_rw_root_nvmem = {
152 .attr = {
153 .name = "nvmem",
154 .mode = 0600,
155 },
156 .read = bin_attr_nvmem_read,
157 .write = bin_attr_nvmem_write,
158};
159
160static struct bin_attribute *nvmem_bin_rw_root_attributes[] = {
161 &bin_attr_rw_root_nvmem,
162 NULL,
163};
164
165static const struct attribute_group nvmem_bin_rw_root_group = {
166 .bin_attrs = nvmem_bin_rw_root_attributes,
167 .attrs = nvmem_attrs,
168};
169
170static const struct attribute_group *nvmem_rw_root_dev_groups[] = {
171 &nvmem_bin_rw_root_group,
172 NULL,
173};
174
175/* read only permission, root only */
176static struct bin_attribute bin_attr_ro_root_nvmem = {
177 .attr = {
178 .name = "nvmem",
179 .mode = 0400,
180 },
181 .read = bin_attr_nvmem_read,
182};
183
184static struct bin_attribute *nvmem_bin_ro_root_attributes[] = {
185 &bin_attr_ro_root_nvmem,
186 NULL,
187};
188
189static const struct attribute_group nvmem_bin_ro_root_group = {
190 .bin_attrs = nvmem_bin_ro_root_attributes,
191 .attrs = nvmem_attrs,
192};
193
194static const struct attribute_group *nvmem_ro_root_dev_groups[] = {
195 &nvmem_bin_ro_root_group,
196 NULL,
197};
198
199const struct attribute_group **nvmem_sysfs_get_groups(
200 struct nvmem_device *nvmem,
201 const struct nvmem_config *config)
202{
203 if (config->root_only)
204 return nvmem->read_only ?
205 nvmem_ro_root_dev_groups :
206 nvmem_rw_root_dev_groups;
207
208 return nvmem->read_only ? nvmem_ro_dev_groups : nvmem_rw_dev_groups;
209}
210
211/*
212 * nvmem_setup_compat() - Create an additional binary entry in
213 * drivers sys directory, to be backwards compatible with the older
214 * drivers/misc/eeprom drivers.
215 */
216int nvmem_sysfs_setup_compat(struct nvmem_device *nvmem,
217 const struct nvmem_config *config)
218{
219 int rval;
220
221 if (!config->compat)
222 return 0;
223
224 if (!config->base_dev)
225 return -EINVAL;
226
227 if (nvmem->read_only)
228 nvmem->eeprom = bin_attr_ro_root_nvmem;
229 else
230 nvmem->eeprom = bin_attr_rw_root_nvmem;
231 nvmem->eeprom.attr.name = "eeprom";
232 nvmem->eeprom.size = nvmem->size;
233#ifdef CONFIG_DEBUG_LOCK_ALLOC
234 nvmem->eeprom.attr.key = &eeprom_lock_key;
235#endif
236 nvmem->eeprom.private = &nvmem->dev;
237 nvmem->base_dev = config->base_dev;
238
239 rval = device_create_bin_file(nvmem->base_dev, &nvmem->eeprom);
240 if (rval) {
241 dev_err(&nvmem->dev,
242 "Failed to create eeprom binary file %d\n", rval);
243 return rval;
244 }
245
246 nvmem->flags |= FLAG_COMPAT;
247
248 return 0;
249}
250
251void nvmem_sysfs_remove_compat(struct nvmem_device *nvmem,
252 const struct nvmem_config *config)
253{
254 if (config->compat)
255 device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
256}
diff --git a/drivers/nvmem/nvmem.h b/drivers/nvmem/nvmem.h
new file mode 100644
index 000000000000..eb8ed7121fa3
--- /dev/null
+++ b/drivers/nvmem/nvmem.h
@@ -0,0 +1,62 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2
3#ifndef _DRIVERS_NVMEM_H
4#define _DRIVERS_NVMEM_H
5
6#include <linux/device.h>
7#include <linux/fs.h>
8#include <linux/kref.h>
9#include <linux/list.h>
10#include <linux/nvmem-consumer.h>
11#include <linux/nvmem-provider.h>
12
13struct nvmem_device {
14 struct module *owner;
15 struct device dev;
16 int stride;
17 int word_size;
18 int id;
19 struct kref refcnt;
20 size_t size;
21 bool read_only;
22 int flags;
23 enum nvmem_type type;
24 struct bin_attribute eeprom;
25 struct device *base_dev;
26 struct list_head cells;
27 nvmem_reg_read_t reg_read;
28 nvmem_reg_write_t reg_write;
29 void *priv;
30};
31
32#define to_nvmem_device(d) container_of(d, struct nvmem_device, dev)
33#define FLAG_COMPAT BIT(0)
34
35#ifdef CONFIG_NVMEM_SYSFS
36const struct attribute_group **nvmem_sysfs_get_groups(
37 struct nvmem_device *nvmem,
38 const struct nvmem_config *config);
39int nvmem_sysfs_setup_compat(struct nvmem_device *nvmem,
40 const struct nvmem_config *config);
41void nvmem_sysfs_remove_compat(struct nvmem_device *nvmem,
42 const struct nvmem_config *config);
43#else
44static inline const struct attribute_group **nvmem_sysfs_get_groups(
45 struct nvmem_device *nvmem,
46 const struct nvmem_config *config)
47{
48 return NULL;
49}
50
51static inline int nvmem_sysfs_setup_compat(struct nvmem_device *nvmem,
52 const struct nvmem_config *config)
53{
54 return -ENOSYS;
55}
56static inline void nvmem_sysfs_remove_compat(struct nvmem_device *nvmem,
57 const struct nvmem_config *config)
58{
59}
60#endif /* CONFIG_NVMEM_SYSFS */
61
62#endif /* _DRIVERS_NVMEM_H */