blob: 5628820b9595aefe52d47a31ee56a793de9208d2 [file] [log] [blame]
Swetha Chikkaboraiahaa9b0662019-04-26 15:21:52 +05301// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2019, Linaro Limited
4 */
5#include "nvmem.h"
6
7#ifdef CONFIG_DEBUG_LOCK_ALLOC
8static struct lock_class_key eeprom_lock_key;
9#endif
10
11static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
12 struct bin_attribute *attr,
13 char *buf, loff_t pos, size_t count)
14{
15 struct device *dev;
16 struct nvmem_device *nvmem;
17 int rc;
18
19 if (attr->private)
20 dev = attr->private;
21 else
22 dev = container_of(kobj, struct device, kobj);
23 nvmem = to_nvmem_device(dev);
24
25 /* Stop the user from reading */
26 if (pos >= nvmem->size)
27 return 0;
28
29 if (count < nvmem->word_size)
30 return -EINVAL;
31
32 if (pos + count > nvmem->size)
33 count = nvmem->size - pos;
34
35 count = round_down(count, nvmem->word_size);
36
37 rc = nvmem->reg_read(nvmem->priv, pos, buf, count);
38
39 if (rc)
40 return rc;
41
42 return count;
43}
44
45static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
46 struct bin_attribute *attr,
47 char *buf, loff_t pos, size_t count)
48{
49 struct device *dev;
50 struct nvmem_device *nvmem;
51 int rc;
52
53 if (attr->private)
54 dev = attr->private;
55 else
56 dev = container_of(kobj, struct device, kobj);
57 nvmem = to_nvmem_device(dev);
58
59 /* Stop the user from writing */
60 if (pos >= nvmem->size)
61 return -EFBIG;
62
63 if (count < nvmem->word_size)
64 return -EINVAL;
65
66 if (pos + count > nvmem->size)
67 count = nvmem->size - pos;
68
69 count = round_down(count, nvmem->word_size);
70
71 rc = nvmem->reg_write(nvmem->priv, pos, buf, count);
72
73 if (rc)
74 return rc;
75
76 return count;
77}
78
79/* default read/write permissions */
80static struct bin_attribute bin_attr_rw_nvmem = {
81 .attr = {
82 .name = "nvmem",
83 .mode = S_IWUSR | S_IRUGO,
84 },
85 .read = bin_attr_nvmem_read,
86 .write = bin_attr_nvmem_write,
87};
88
89static struct bin_attribute *nvmem_bin_rw_attributes[] = {
90 &bin_attr_rw_nvmem,
91 NULL,
92};
93
94static const struct attribute_group nvmem_bin_rw_group = {
95 .bin_attrs = nvmem_bin_rw_attributes,
96};
97
98static const struct attribute_group *nvmem_rw_dev_groups[] = {
99 &nvmem_bin_rw_group,
100 NULL,
101};
102
103/* read only permission */
104static struct bin_attribute bin_attr_ro_nvmem = {
105 .attr = {
106 .name = "nvmem",
107 .mode = S_IRUGO,
108 },
109 .read = bin_attr_nvmem_read,
110};
111
112static struct bin_attribute *nvmem_bin_ro_attributes[] = {
113 &bin_attr_ro_nvmem,
114 NULL,
115};
116
117static const struct attribute_group nvmem_bin_ro_group = {
118 .bin_attrs = nvmem_bin_ro_attributes,
119};
120
121static const struct attribute_group *nvmem_ro_dev_groups[] = {
122 &nvmem_bin_ro_group,
123 NULL,
124};
125
126/* default read/write permissions, root only */
127static struct bin_attribute bin_attr_rw_root_nvmem = {
128 .attr = {
129 .name = "nvmem",
130 .mode = S_IWUSR | S_IRUSR,
131 },
132 .read = bin_attr_nvmem_read,
133 .write = bin_attr_nvmem_write,
134};
135
136static struct bin_attribute *nvmem_bin_rw_root_attributes[] = {
137 &bin_attr_rw_root_nvmem,
138 NULL,
139};
140
141static const struct attribute_group nvmem_bin_rw_root_group = {
142 .bin_attrs = nvmem_bin_rw_root_attributes,
143};
144
145static const struct attribute_group *nvmem_rw_root_dev_groups[] = {
146 &nvmem_bin_rw_root_group,
147 NULL,
148};
149
150/* read only permission, root only */
151static struct bin_attribute bin_attr_ro_root_nvmem = {
152 .attr = {
153 .name = "nvmem",
154 .mode = S_IRUSR,
155 },
156 .read = bin_attr_nvmem_read,
157};
158
159static struct bin_attribute *nvmem_bin_ro_root_attributes[] = {
160 &bin_attr_ro_root_nvmem,
161 NULL,
162};
163
164static const struct attribute_group nvmem_bin_ro_root_group = {
165 .bin_attrs = nvmem_bin_ro_root_attributes,
166};
167
168static const struct attribute_group *nvmem_ro_root_dev_groups[] = {
169 &nvmem_bin_ro_root_group,
170 NULL,
171};
172
173const struct attribute_group **nvmem_sysfs_get_groups(
174 struct nvmem_device *nvmem,
175 const struct nvmem_config *config)
176{
177 if (config->root_only)
178 return nvmem->read_only ?
179 nvmem_ro_root_dev_groups :
180 nvmem_rw_root_dev_groups;
181
182 return nvmem->read_only ? nvmem_ro_dev_groups : nvmem_rw_dev_groups;
183}
184
185/*
186 * nvmem_setup_compat() - Create an additional binary entry in
187 * drivers sys directory, to be backwards compatible with the older
188 * drivers/misc/eeprom drivers.
189 */
190int nvmem_sysfs_setup_compat(struct nvmem_device *nvmem,
191 const struct nvmem_config *config)
192{
193 int rval;
194
195 if (!config->compat)
196 return 0;
197
198 if (!config->base_dev)
199 return -EINVAL;
200
jianzhou4be63542019-12-02 13:57:22 +0800201 if (nvmem->read_only) {
202 if (config->root_only)
203 nvmem->eeprom = bin_attr_ro_root_nvmem;
204 else
205 nvmem->eeprom = bin_attr_ro_nvmem;
206 } else {
207 if (config->root_only)
208 nvmem->eeprom = bin_attr_rw_root_nvmem;
209 else
210 nvmem->eeprom = bin_attr_rw_nvmem;
211 }
Swetha Chikkaboraiahaa9b0662019-04-26 15:21:52 +0530212 nvmem->eeprom.attr.name = "eeprom";
213 nvmem->eeprom.size = nvmem->size;
214#ifdef CONFIG_DEBUG_LOCK_ALLOC
215 nvmem->eeprom.attr.key = &eeprom_lock_key;
216#endif
217 nvmem->eeprom.private = &nvmem->dev;
218 nvmem->base_dev = config->base_dev;
219
220 rval = device_create_bin_file(nvmem->base_dev, &nvmem->eeprom);
221 if (rval) {
222 dev_err(&nvmem->dev,
223 "Failed to create eeprom binary file %d\n", rval);
224 return rval;
225 }
226
227 nvmem->flags |= FLAG_COMPAT;
228
229 return 0;
230}
231
232void nvmem_sysfs_remove_compat(struct nvmem_device *nvmem,
233 const struct nvmem_config *config)
234{
235 if (config->compat)
236 device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
237}