• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
w1_ds2502_read_page(struct w1_slave * sl,int pageno)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 
w1_ds2505_read_page(struct w1_slave * sl,int pageno)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 
w1_nvmem_read(void * priv,unsigned int off,void * buf,size_t count)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 
w1_eprom_add_slave(struct w1_slave * sl)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 const 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 
w1_ds250x_init(void)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 
w1_ds250x_exit(void)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));
291