1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Driver for DS-2502 One wire "Add only Memory".
4  *
5  * The chip has 4 pages of 32 bytes.
6  * In addition it has 8 out of band status bytes that are used, by software,
7  * as page redirection bytes by an algorithm described in the data sheet.
8  * This is useful since data cannot be erased once written but it can be
9  * "patched" up to four times by switching pages.
10  *
11  * So, when a read request is entirely in the first page automatically
12  * apply the page redirection bytes (which allows the device to be seen as
13  * a 32 byte PROM, writable 4 times).
14  *
15  * If the read request is outside of or larger than the first page then read
16  * the raw data (which allows the device to be seen as a 128 byte PROM,
17  * writable once).
18  *
19  * Copyright (c) 2018 Flowbird
20  * Martin Fuzzey <martin.fuzzey@flowbird.group>
21  */
22 
23 #include <common.h>
24 #include <dm.h>
25 #include <dm/device_compat.h>
26 #include <linux/err.h>
27 #include <w1-eeprom.h>
28 #include <w1.h>
29 
30 #define DS2502_PAGE_SIZE	32
31 #define DS2502_PAGE_COUNT	4
32 #define DS2502_STATUS_SIZE	8
33 
34 #define DS2502_CMD_READ_STATUS	0xAA
35 #define DS2502_CMD_READ_GEN_CRC	0xC3
36 
37 /* u-boot crc8() is CCITT CRC8, we need x^8 + x^5 + x^4 + 1 LSB first */
ds2502_crc8(const u8 * buf,int len)38 static unsigned int ds2502_crc8(const u8 *buf, int len)
39 {
40 	static const u8 poly = 0x8C;  /* (1 + x^4 + x^5) + x^8 */
41 	u8 crc = 0;
42 	int i;
43 
44 	for (i = 0; i < len; i++) {
45 		u8 data = buf[i];
46 		int j;
47 
48 		for (j = 0; j < 8; j++) {
49 			u8 mix = (crc ^ data) & 1;
50 
51 			crc >>= 1;
52 			if (mix)
53 				crc ^= poly;
54 			data >>= 1;
55 		}
56 	}
57 	return crc;
58 }
59 
ds2502_read(struct udevice * dev,u8 cmd,int bytes_in_page,int pos,u8 * buf,int bytes_for_user)60 static int ds2502_read(struct udevice *dev, u8 cmd,
61 		       int bytes_in_page, int pos,
62 		       u8 *buf, int bytes_for_user)
63 {
64 	int retry;
65 	int ret = 0;
66 
67 	for (retry = 0; retry < 3; retry++) {
68 		u8 pagebuf[DS2502_PAGE_SIZE + 1]; /* 1 byte for CRC8 */
69 		u8 crc;
70 		int i;
71 
72 		ret = w1_reset_select(dev);
73 		if (ret)
74 			return ret;
75 
76 		/* send read to end of page and generate CRC command */
77 		pagebuf[0] = cmd;
78 		pagebuf[1] = pos & 0xff;
79 		pagebuf[2] = pos >> 8;
80 		crc = ds2502_crc8(pagebuf, 3);
81 		for (i = 0; i < 3; i++)
82 			w1_write_byte(dev, pagebuf[i]);
83 
84 		/* Check command CRC */
85 		ret = w1_read_byte(dev);
86 		if (ret < 0) {
87 			dev_dbg(dev, "Error %d reading command CRC\n", ret);
88 			continue;
89 		}
90 
91 		if (ret != crc) {
92 			dev_dbg(dev,
93 				"bad CRC8 for cmd %02x got=%02X exp=%02X\n",
94 				cmd, ret, crc);
95 			ret = -EIO;
96 			continue;
97 		}
98 
99 		/* read data and check CRC */
100 		ret = w1_read_buf(dev, pagebuf, bytes_in_page + 1);
101 		if (ret < 0) {
102 			dev_dbg(dev, "Error %d reading data\n", ret);
103 			continue;
104 		}
105 
106 		crc = ds2502_crc8(pagebuf, bytes_in_page);
107 		if (crc == pagebuf[bytes_in_page]) {
108 			memcpy(buf, pagebuf, bytes_for_user);
109 			ret = 0;
110 			break;
111 		}
112 		dev_dbg(dev, "Bad CRC8 got=%02X exp=%02X pos=%04X\n",
113 			pagebuf[bytes_in_page], crc, pos);
114 		ret = -EIO;
115 	}
116 
117 	return ret;
118 }
119 
ds2502_read_status_bytes(struct udevice * dev,u8 * buf)120 static inline int ds2502_read_status_bytes(struct udevice *dev, u8 *buf)
121 {
122 	return ds2502_read(dev, DS2502_CMD_READ_STATUS,
123 				DS2502_STATUS_SIZE, 0,
124 				buf, DS2502_STATUS_SIZE);
125 }
126 
127 /*
128  * Status bytes (from index 1) contain 1's complement page indirection
129  * So for N writes:
130  * N=1: ff ff ff ff ff ff ff 00
131  * N=2: ff fe ff ff ff ff ff 00
132  * N=3: ff fe fd ff ff ff ff 00
133  * N=4: ff fe fd fc ff ff ff 00
134  */
ds2502_indirect_page(struct udevice * dev,u8 * status,int page)135 static int ds2502_indirect_page(struct udevice *dev, u8 *status, int page)
136 {
137 	int page_seen = 0;
138 
139 	do {
140 		u8 sb = status[page + 1];
141 
142 		if (sb == 0xff)
143 			break;
144 
145 		page = ~sb & 0xff;
146 
147 		if (page >= DS2502_PAGE_COUNT) {
148 			dev_err(dev,
149 				"Illegal page redirection status byte %02x\n",
150 				sb);
151 			return -EINVAL;
152 		}
153 
154 		if (page_seen & (1 << page)) {
155 			dev_err(dev, "Infinite loop in page redirection\n");
156 			return -EINVAL;
157 		}
158 
159 		page_seen |= (1 << page);
160 	} while (1);
161 
162 	return page;
163 }
164 
ds2502_read_buf(struct udevice * dev,unsigned int offset,u8 * buf,unsigned int count)165 static int ds2502_read_buf(struct udevice *dev, unsigned int offset,
166 			   u8 *buf, unsigned int count)
167 {
168 	unsigned int min_page = offset / DS2502_PAGE_SIZE;
169 	unsigned int max_page = (offset + count - 1) / DS2502_PAGE_SIZE;
170 	int xfered = 0;
171 	u8 status_bytes[DS2502_STATUS_SIZE];
172 	int i;
173 	int ret;
174 
175 	if (min_page >= DS2502_PAGE_COUNT || max_page >= DS2502_PAGE_COUNT)
176 		return -EINVAL;
177 
178 	if (min_page == 0 && max_page == 0) {
179 		ret = ds2502_read_status_bytes(dev, status_bytes);
180 		if (ret)
181 			return ret;
182 	} else {
183 		/* Dummy one to one page redirection */
184 		memset(status_bytes, 0xff, sizeof(status_bytes));
185 	}
186 
187 	for (i = min_page; i <= max_page; i++) {
188 		int page;
189 		int pos;
190 		int bytes_in_page;
191 		int bytes_for_user;
192 
193 		page = ds2502_indirect_page(dev, status_bytes, i);
194 		if (page < 0)
195 			return page;
196 		dev_dbg(dev, "page logical %d => physical %d\n", i, page);
197 
198 		pos = page * DS2502_PAGE_SIZE;
199 		if (i == min_page)
200 			pos += offset % DS2502_PAGE_SIZE;
201 
202 		bytes_in_page = DS2502_PAGE_SIZE - (pos % DS2502_PAGE_SIZE);
203 
204 		if (i == max_page)
205 			bytes_for_user = count - xfered;
206 		else
207 			bytes_for_user = bytes_in_page;
208 
209 		ret = ds2502_read(dev, DS2502_CMD_READ_GEN_CRC,
210 				  bytes_in_page, pos,
211 				  &buf[xfered], bytes_for_user);
212 		if (ret < 0)
213 			return ret;
214 
215 		xfered += bytes_for_user;
216 	}
217 
218 	return 0;
219 }
220 
ds2502_probe(struct udevice * dev)221 static int ds2502_probe(struct udevice *dev)
222 {
223 	struct w1_device *w1;
224 
225 	w1 = dev_get_parent_plat(dev);
226 	w1->id = 0;
227 	return 0;
228 }
229 
230 static const struct w1_eeprom_ops ds2502_ops = {
231 	.read_buf	= ds2502_read_buf,
232 };
233 
234 static const struct udevice_id ds2502_id[] = {
235 	{ .compatible = "maxim,ds2502", .data = W1_FAMILY_DS2502 },
236 	{ },
237 };
238 
239 U_BOOT_DRIVER(ds2502) = {
240 	.name		= "ds2502",
241 	.id		= UCLASS_W1_EEPROM,
242 	.of_match	= ds2502_id,
243 	.ops		= &ds2502_ops,
244 	.probe		= ds2502_probe,
245 };
246 
247 u8 family_supported[] = {
248 	W1_FAMILY_DS2502,
249 };
250 
251 U_BOOT_W1_DEVICE(ds2502, family_supported);
252