Merge tag 'trace-v5.11-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
[linux/fpc-iii.git] / drivers / w1 / slaves / w1_ds250x.c
blob7592c7050d1d7de19ecad038603acab3f74324f3
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * w1_ds250x.c - w1 family 09/0b/89/91 (DS250x) driver
4 */
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>
15 #include <linux/w1.h>
16 #include <linux/nvmem-provider.h>
18 #define W1_DS2501_UNW_FAMILY 0x91
19 #define W1_DS2501_SIZE 64
21 #define W1_DS2502_FAMILY 0x09
22 #define W1_DS2502_UNW_FAMILY 0x89
23 #define W1_DS2502_SIZE 128
25 #define W1_DS2505_FAMILY 0x0b
26 #define W1_DS2505_SIZE 2048
28 #define W1_PAGE_SIZE 32
30 #define W1_EXT_READ_MEMORY 0xA5
31 #define W1_READ_DATA_CRC 0xC3
33 #define OFF2PG(off) ((off) / W1_PAGE_SIZE)
35 #define CRC16_INIT 0
36 #define CRC16_VALID 0xb001
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];
46 static int w1_ds2502_read_page(struct w1_slave *sl, int pageno)
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;
54 if (test_bit(pageno, data->page_present))
55 return 0; /* page already present */
57 mutex_lock(&sl->master->bus_mutex);
59 if (w1_reset_select_slave(sl))
60 goto err;
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);
67 crc8 = w1_read_8(sl->master);
68 if (w1_calc_crc8(buf, 3) != crc8)
69 goto err;
71 w1_read_block(sl->master, &data->eprom[pgoff], W1_PAGE_SIZE);
73 crc8 = w1_read_8(sl->master);
74 if (w1_calc_crc8(&data->eprom[pgoff], W1_PAGE_SIZE) != crc8)
75 goto err;
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;
84 static int w1_ds2505_read_page(struct w1_slave *sl, int pageno)
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;
94 if (test_bit(pageno, data->page_present))
95 return 0; /* page already present */
97 epoff = pgoff = pageno * W1_PAGE_SIZE;
98 mutex_lock(&sl->master->bus_mutex);
100 retry:
101 if (w1_reset_select_slave(sl))
102 goto err;
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);
112 if (crc != CRC16_VALID)
113 goto err;
116 if (redir != 0xff) {
117 redir_retries--;
118 if (redir_retries < 0)
119 goto err;
121 pgoff = (redir ^ 0xff) * W1_PAGE_SIZE;
122 goto retry;
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);
130 if (crc != CRC16_VALID)
131 goto err;
133 set_bit(pageno, data->page_present);
134 ret = 0;
135 err:
136 mutex_unlock(&sl->master->bus_mutex);
137 return ret;
140 static int w1_nvmem_read(void *priv, unsigned int off, void *buf, size_t count)
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;
148 if (off > eprom_size)
149 return -EINVAL;
151 if ((off + count) > eprom_size)
152 count = eprom_size - off;
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));
161 memcpy(buf, &data->eprom[off], count);
162 return 0;
165 static int w1_eprom_add_slave(struct w1_slave *sl)
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
179 data = devm_kzalloc(&sl->dev, sizeof(struct w1_eprom_data), GFP_KERNEL);
180 if (!data)
181 return -ENOMEM;
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;
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);
211 nvmem_cfg.name = data->nvmem_name;
212 nvmem_cfg.size = data->size;
214 nvmem = devm_nvmem_register(&sl->dev, &nvmem_cfg);
215 return PTR_ERR_OR_ZERO(nvmem);
218 static const struct w1_family_ops w1_eprom_fops = {
219 .add_slave = w1_eprom_add_slave,
222 static struct w1_family w1_family_09 = {
223 .fid = W1_DS2502_FAMILY,
224 .fops = &w1_eprom_fops,
227 static struct w1_family w1_family_0b = {
228 .fid = W1_DS2505_FAMILY,
229 .fops = &w1_eprom_fops,
232 static struct w1_family w1_family_89 = {
233 .fid = W1_DS2502_UNW_FAMILY,
234 .fops = &w1_eprom_fops,
237 static struct w1_family w1_family_91 = {
238 .fid = W1_DS2501_UNW_FAMILY,
239 .fops = &w1_eprom_fops,
242 static int __init w1_ds250x_init(void)
244 int err;
246 err = w1_register_family(&w1_family_09);
247 if (err)
248 return err;
250 err = w1_register_family(&w1_family_0b);
251 if (err)
252 goto err_0b;
254 err = w1_register_family(&w1_family_89);
255 if (err)
256 goto err_89;
258 err = w1_register_family(&w1_family_91);
259 if (err)
260 goto err_91;
262 return 0;
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;
273 static void __exit w1_ds250x_exit(void)
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);
281 module_init(w1_ds250x_init);
282 module_exit(w1_ds250x_exit);
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));