Linux-libre 5.4.47-gnu
[librecmc/linux-libre.git] / drivers / w1 / slaves / w1_ds250x.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * w1_ds250x.c - w1 family 09/0b/89/91 (DS250x) driver
4  */
5
6 #include <linux/kernel.h>
7 #include <linux/module.h>
8 #include <linux/moduleparam.h>
9 #include <linux/device.h>
10 #include <linux/types.h>
11 #include <linux/delay.h>
12 #include <linux/slab.h>
13 #include <linux/crc16.h>
14
15 #include <linux/w1.h>
16 #include <linux/nvmem-provider.h>
17
18 #define W1_DS2501_UNW_FAMILY    0x91
19 #define W1_DS2501_SIZE          64
20
21 #define W1_DS2502_FAMILY        0x09
22 #define W1_DS2502_UNW_FAMILY    0x89
23 #define W1_DS2502_SIZE          128
24
25 #define W1_DS2505_FAMILY        0x0b
26 #define W1_DS2505_SIZE          2048
27
28 #define W1_PAGE_SIZE            32
29
30 #define W1_EXT_READ_MEMORY      0xA5
31 #define W1_READ_DATA_CRC        0xC3
32
33 #define OFF2PG(off)     ((off) / W1_PAGE_SIZE)
34
35 #define CRC16_INIT              0
36 #define CRC16_VALID             0xb001
37
38 struct w1_eprom_data {
39         size_t size;
40         int (*read)(struct w1_slave *sl, int pageno);
41         u8 eprom[W1_DS2505_SIZE];
42         DECLARE_BITMAP(page_present, W1_DS2505_SIZE / W1_PAGE_SIZE);
43         char nvmem_name[64];
44 };
45
46 static int w1_ds2502_read_page(struct w1_slave *sl, int pageno)
47 {
48         struct w1_eprom_data *data = sl->family_data;
49         int pgoff = pageno * W1_PAGE_SIZE;
50         int ret = -EIO;
51         u8 buf[3];
52         u8 crc8;
53
54         if (test_bit(pageno, data->page_present))
55                 return 0; /* page already present */
56
57         mutex_lock(&sl->master->bus_mutex);
58
59         if (w1_reset_select_slave(sl))
60                 goto err;
61
62         buf[0] = W1_READ_DATA_CRC;
63         buf[1] = pgoff & 0xff;
64         buf[2] = pgoff >> 8;
65         w1_write_block(sl->master, buf, 3);
66
67         crc8 = w1_read_8(sl->master);
68         if (w1_calc_crc8(buf, 3) != crc8)
69                 goto err;
70
71         w1_read_block(sl->master, &data->eprom[pgoff], W1_PAGE_SIZE);
72
73         crc8 = w1_read_8(sl->master);
74         if (w1_calc_crc8(&data->eprom[pgoff], W1_PAGE_SIZE) != crc8)
75                 goto err;
76
77         set_bit(pageno, data->page_present); /* mark page present */
78         ret = 0;
79 err:
80         mutex_unlock(&sl->master->bus_mutex);
81         return ret;
82 }
83
84 static int w1_ds2505_read_page(struct w1_slave *sl, int pageno)
85 {
86         struct w1_eprom_data *data = sl->family_data;
87         int redir_retries = 16;
88         int pgoff, epoff;
89         int ret = -EIO;
90         u8 buf[6];
91         u8 redir;
92         u16 crc;
93
94         if (test_bit(pageno, data->page_present))
95                 return 0; /* page already present */
96
97         epoff = pgoff = pageno * W1_PAGE_SIZE;
98         mutex_lock(&sl->master->bus_mutex);
99
100 retry:
101         if (w1_reset_select_slave(sl))
102                 goto err;
103
104         buf[0] = W1_EXT_READ_MEMORY;
105         buf[1] = pgoff & 0xff;
106         buf[2] = pgoff >> 8;
107         w1_write_block(sl->master, buf, 3);
108         w1_read_block(sl->master, buf + 3, 3); /* redir, crc16 */
109         redir = buf[3];
110         crc = crc16(CRC16_INIT, buf, 6);
111
112         if (crc != CRC16_VALID)
113                 goto err;
114
115
116         if (redir != 0xff) {
117                 redir_retries--;
118                 if (redir_retries < 0)
119                         goto err;
120
121                 pgoff = (redir ^ 0xff) * W1_PAGE_SIZE;
122                 goto retry;
123         }
124
125         w1_read_block(sl->master, &data->eprom[epoff], W1_PAGE_SIZE);
126         w1_read_block(sl->master, buf, 2); /* crc16 */
127         crc = crc16(CRC16_INIT, &data->eprom[epoff], W1_PAGE_SIZE);
128         crc = crc16(crc, buf, 2);
129
130         if (crc != CRC16_VALID)
131                 goto err;
132
133         set_bit(pageno, data->page_present);
134         ret = 0;
135 err:
136         mutex_unlock(&sl->master->bus_mutex);
137         return ret;
138 }
139
140 static int w1_nvmem_read(void *priv, unsigned int off, void *buf, size_t count)
141 {
142         struct w1_slave *sl = priv;
143         struct w1_eprom_data *data = sl->family_data;
144         size_t eprom_size = data->size;
145         int ret;
146         int i;
147
148         if (off > eprom_size)
149                 return -EINVAL;
150
151         if ((off + count) > eprom_size)
152                 count = eprom_size - off;
153
154         i = OFF2PG(off);
155         do {
156                 ret = data->read(sl, i++);
157                 if (ret < 0)
158                         return ret;
159         } while (i < OFF2PG(off + count));
160
161         memcpy(buf, &data->eprom[off], count);
162         return 0;
163 }
164
165 static int w1_eprom_add_slave(struct w1_slave *sl)
166 {
167         struct w1_eprom_data *data;
168         struct nvmem_device *nvmem;
169         struct nvmem_config nvmem_cfg = {
170                 .dev = &sl->dev,
171                 .reg_read = w1_nvmem_read,
172                 .type = NVMEM_TYPE_OTP,
173                 .read_only = true,
174                 .word_size = 1,
175                 .priv = sl,
176                 .id = -1
177         };
178
179         data = devm_kzalloc(&sl->dev, sizeof(struct w1_eprom_data), GFP_KERNEL);
180         if (!data)
181                 return -ENOMEM;
182
183         sl->family_data = data;
184         switch (sl->family->fid) {
185         case W1_DS2501_UNW_FAMILY:
186                 data->size = W1_DS2501_SIZE;
187                 data->read = w1_ds2502_read_page;
188                 break;
189         case W1_DS2502_FAMILY:
190         case W1_DS2502_UNW_FAMILY:
191                 data->size = W1_DS2502_SIZE;
192                 data->read = w1_ds2502_read_page;
193                 break;
194         case W1_DS2505_FAMILY:
195                 data->size = W1_DS2505_SIZE;
196                 data->read = w1_ds2505_read_page;
197                 break;
198         }
199
200         if (sl->master->bus_master->dev_id)
201                 snprintf(data->nvmem_name, sizeof(data->nvmem_name),
202                          "%s-%02x-%012llx",
203                          sl->master->bus_master->dev_id, sl->reg_num.family,
204                          (unsigned long long)sl->reg_num.id);
205         else
206                 snprintf(data->nvmem_name, sizeof(data->nvmem_name),
207                          "%02x-%012llx",
208                          sl->reg_num.family,
209                          (unsigned long long)sl->reg_num.id);
210
211         nvmem_cfg.name = data->nvmem_name;
212         nvmem_cfg.size = data->size;
213
214         nvmem = devm_nvmem_register(&sl->dev, &nvmem_cfg);
215         return PTR_ERR_OR_ZERO(nvmem);
216 }
217
218 static struct w1_family_ops w1_eprom_fops = {
219         .add_slave      = w1_eprom_add_slave,
220 };
221
222 static struct w1_family w1_family_09 = {
223         .fid = W1_DS2502_FAMILY,
224         .fops = &w1_eprom_fops,
225 };
226
227 static struct w1_family w1_family_0b = {
228         .fid = W1_DS2505_FAMILY,
229         .fops = &w1_eprom_fops,
230 };
231
232 static struct w1_family w1_family_89 = {
233         .fid = W1_DS2502_UNW_FAMILY,
234         .fops = &w1_eprom_fops,
235 };
236
237 static struct w1_family w1_family_91 = {
238         .fid = W1_DS2501_UNW_FAMILY,
239         .fops = &w1_eprom_fops,
240 };
241
242 static int __init w1_ds250x_init(void)
243 {
244         int err;
245
246         err = w1_register_family(&w1_family_09);
247         if (err)
248                 return err;
249
250         err = w1_register_family(&w1_family_0b);
251         if (err)
252                 goto err_0b;
253
254         err = w1_register_family(&w1_family_89);
255         if (err)
256                 goto err_89;
257
258         err = w1_register_family(&w1_family_91);
259         if (err)
260                 goto err_91;
261
262         return 0;
263
264 err_91:
265         w1_unregister_family(&w1_family_89);
266 err_89:
267         w1_unregister_family(&w1_family_0b);
268 err_0b:
269         w1_unregister_family(&w1_family_09);
270         return err;
271 }
272
273 static void __exit w1_ds250x_exit(void)
274 {
275         w1_unregister_family(&w1_family_09);
276         w1_unregister_family(&w1_family_0b);
277         w1_unregister_family(&w1_family_89);
278         w1_unregister_family(&w1_family_91);
279 }
280
281 module_init(w1_ds250x_init);
282 module_exit(w1_ds250x_exit);
283
284 MODULE_AUTHOR("Thomas Bogendoerfer <tbogendoerfe@suse.de>");
285 MODULE_DESCRIPTION("w1 family driver for DS250x Add Only Memory");
286 MODULE_LICENSE("GPL");
287 MODULE_ALIAS("w1-family-" __stringify(W1_DS2502_FAMILY));
288 MODULE_ALIAS("w1-family-" __stringify(W1_DS2505_FAMILY));
289 MODULE_ALIAS("w1-family-" __stringify(W1_DS2501_UNW_FAMILY));
290 MODULE_ALIAS("w1-family-" __stringify(W1_DS2502_UNW_FAMILY));