1 /*
2  * I2C Driver for Atmel ATSHA204 over I2C
3  *
4  * Copyright (C) 2014 Josh Datko, Cryptotronix, jbd@cryptotronix.com
5  * 		 2016 Tomas Hlavacek, CZ.NIC, tmshlvck@gmail.com
6  * 		 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
7  *
8  * This program is free software; you can redistribute  it and/or modify it
9  * under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12 
13 #include <common.h>
14 #include <dm.h>
15 #include <i2c.h>
16 #include <errno.h>
17 #include <atsha204a-i2c.h>
18 #include <log.h>
19 #include <asm/global_data.h>
20 #include <linux/delay.h>
21 #include <u-boot/crc.h>
22 
23 #define ATSHA204A_TWLO			60
24 #define ATSHA204A_TRANSACTION_TIMEOUT	100000
25 #define ATSHA204A_TRANSACTION_RETRY	5
26 #define ATSHA204A_EXECTIME		5000
27 
28 DECLARE_GLOBAL_DATA_PTR;
29 
30 /*
31  * The ATSHA204A uses an (to me) unknown CRC-16 algorithm.
32  * The Reveng CRC-16 catalogue does not contain it.
33  *
34  * Because in Atmel's documentation only a primitive implementation
35  * can be found, I have implemented this one with lookup table.
36  */
37 
38 /*
39  * This is the code that computes the table below:
40  *
41  * int i, j;
42  * for (i = 0; i < 256; ++i) {
43  * 	u8 c = 0;
44  * 	for (j = 0; j < 8; ++j) {
45  * 		c = (c << 1) | ((i >> j) & 1);
46  * 	}
47  * 	bitreverse_table[i] = c;
48  * }
49  */
50 
51 static u8 const bitreverse_table[256] = {
52 	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
53 	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
54 	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
55 	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
56 	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
57 	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
58 	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
59 	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
60 	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
61 	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
62 	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
63 	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
64 	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
65 	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
66 	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
67 	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
68 	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
69 	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
70 	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
71 	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
72 	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
73 	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
74 	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
75 	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
76 	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
77 	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
78 	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
79 	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
80 	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
81 	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
82 	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
83 	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
84 };
85 
86 /*
87  * This is the code that computes the table below:
88  *
89  * int i, j;
90  * for (i = 0; i < 256; ++i) {
91  * 	u16 c = i << 8;
92  * 	for (j = 0; j < 8; ++j) {
93  * 		int b = c >> 15;
94  * 		c <<= 1;
95  * 		if (b)
96  * 			c ^= 0x8005;
97  * 	}
98  * 	crc16_table[i] = c;
99  * }
100  */
101 static u16 const crc16_table[256] = {
102 	0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011,
103 	0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022,
104 	0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072,
105 	0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041,
106 	0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2,
107 	0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1,
108 	0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1,
109 	0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082,
110 	0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192,
111 	0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1,
112 	0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1,
113 	0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2,
114 	0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151,
115 	0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162,
116 	0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132,
117 	0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101,
118 	0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312,
119 	0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321,
120 	0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371,
121 	0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342,
122 	0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1,
123 	0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2,
124 	0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2,
125 	0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381,
126 	0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291,
127 	0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2,
128 	0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2,
129 	0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1,
130 	0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252,
131 	0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261,
132 	0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231,
133 	0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202,
134 };
135 
crc16_byte(u16 crc,const u8 data)136 static inline u16 crc16_byte(u16 crc, const u8 data)
137 {
138 	u16 t = crc16_table[((crc >> 8) ^ bitreverse_table[data]) & 0xff];
139 	return ((crc << 8) ^ t);
140 }
141 
atsha204a_crc16(const u8 * buffer,size_t len)142 static u16 atsha204a_crc16(const u8 *buffer, size_t len)
143 {
144 	u16 crc = 0;
145 
146 	while (len--)
147 		crc = crc16_byte(crc, *buffer++);
148 
149 	return cpu_to_le16(crc);
150 }
151 
atsha204a_send(struct udevice * dev,const u8 * buf,u8 len)152 static int atsha204a_send(struct udevice *dev, const u8 *buf, u8 len)
153 {
154 	fdt_addr_t *priv = dev_get_priv(dev);
155 	struct i2c_msg msg;
156 
157 	msg.addr = *priv;
158 	msg.flags = I2C_M_STOP;
159 	msg.len = len;
160 	msg.buf = (u8 *) buf;
161 
162 	return dm_i2c_xfer(dev, &msg, 1);
163 }
164 
atsha204a_recv(struct udevice * dev,u8 * buf,u8 len)165 static int atsha204a_recv(struct udevice *dev, u8 *buf, u8 len)
166 {
167 	fdt_addr_t *priv = dev_get_priv(dev);
168 	struct i2c_msg msg;
169 
170 	msg.addr = *priv;
171 	msg.flags = I2C_M_RD | I2C_M_STOP;
172 	msg.len = len;
173 	msg.buf = (u8 *) buf;
174 
175 	return dm_i2c_xfer(dev, &msg, 1);
176 }
177 
atsha204a_recv_resp(struct udevice * dev,struct atsha204a_resp * resp)178 static int atsha204a_recv_resp(struct udevice *dev,
179 			       struct atsha204a_resp *resp)
180 {
181 	int res;
182 	u16 resp_crc, computed_crc;
183 	u8 *p = (u8 *) resp;
184 
185 	res = atsha204a_recv(dev, p, 4);
186 	if (res)
187 		return res;
188 
189 	if (resp->length > 4) {
190 		if (resp->length > sizeof(*resp))
191 			return -EMSGSIZE;
192 
193 		res = atsha204a_recv(dev, p + 4, resp->length - 4);
194 		if (res)
195 			return res;
196 	}
197 
198 	resp_crc = (u16) p[resp->length - 2]
199 		   | (((u16) p[resp->length - 1]) << 8);
200 	computed_crc = atsha204a_crc16(p, resp->length - 2);
201 
202 	if (resp_crc != computed_crc) {
203 		debug("Invalid checksum in ATSHA204A response\n");
204 		return -EBADMSG;
205 	}
206 
207 	return 0;
208 }
209 
atsha204a_wakeup(struct udevice * dev)210 int atsha204a_wakeup(struct udevice *dev)
211 {
212 	u8 req[4];
213 	struct atsha204a_resp resp;
214 	int try, res;
215 
216 	debug("Waking up ATSHA204A\n");
217 
218 	for (try = 1; try <= 10; ++try) {
219 		debug("Try %i... ", try);
220 
221 		memset(req, 0, 4);
222 		res = atsha204a_send(dev, req, 4);
223 		if (res) {
224 			debug("failed on I2C send, trying again\n");
225 			continue;
226 		}
227 
228 		udelay(ATSHA204A_TWLO);
229 
230 		res = atsha204a_recv_resp(dev, &resp);
231 		if (res) {
232 			debug("failed on receiving response, ending\n");
233 			return res;
234 		}
235 
236 		if (resp.code != ATSHA204A_STATUS_AFTER_WAKE) {
237 			debug ("failed (responce code = %02x), ending\n",
238 			       resp.code);
239 			return -EBADMSG;
240 		}
241 
242 		debug("success\n");
243 		break;
244 	}
245 
246 	return 0;
247 }
248 
atsha204a_idle(struct udevice * dev)249 int atsha204a_idle(struct udevice *dev)
250 {
251 	int res;
252 	u8 req = ATSHA204A_FUNC_IDLE;
253 
254 	res = atsha204a_send(dev, &req, 1);
255 	if (res)
256 		debug("Failed putting ATSHA204A idle\n");
257 	return res;
258 }
259 
atsha204a_sleep(struct udevice * dev)260 int atsha204a_sleep(struct udevice *dev)
261 {
262 	int res;
263 	u8 req = ATSHA204A_FUNC_IDLE;
264 
265 	res = atsha204a_send(dev, &req, 1);
266 	if (res)
267 		debug("Failed putting ATSHA204A to sleep\n");
268 	return res;
269 }
270 
atsha204a_transaction(struct udevice * dev,struct atsha204a_req * req,struct atsha204a_resp * resp)271 static int atsha204a_transaction(struct udevice *dev, struct atsha204a_req *req,
272 				struct atsha204a_resp *resp)
273 {
274 	int res, timeout = ATSHA204A_TRANSACTION_TIMEOUT;
275 
276 	res = atsha204a_send(dev, (u8 *) req, req->length + 1);
277 	if (res) {
278 		debug("ATSHA204A transaction send failed\n");
279 		return -EBUSY;
280 	}
281 
282 	do {
283 		res = atsha204a_recv_resp(dev, resp);
284 		if (!res || res == -EMSGSIZE || res == -EBADMSG)
285 			break;
286 
287 		debug("ATSHA204A transaction polling for response "
288 		      "(timeout = %d)\n", timeout);
289 
290 		udelay(ATSHA204A_EXECTIME);
291 		timeout -= ATSHA204A_EXECTIME;
292 	} while (timeout > 0);
293 
294 	if (timeout <= 0) {
295 		debug("ATSHA204A transaction timed out\n");
296 		return -ETIMEDOUT;
297 	}
298 
299 	return res;
300 }
301 
atsha204a_req_crc32(struct atsha204a_req * req)302 static void atsha204a_req_crc32(struct atsha204a_req *req)
303 {
304 	u8 *p = (u8 *) req;
305 	u16 computed_crc;
306 	u16 *crc_ptr = (u16 *) &p[req->length - 1];
307 
308 	/* The buffer to crc16 starts at byte 1, not 0 */
309 	computed_crc = atsha204a_crc16(p + 1, req->length - 2);
310 
311 	*crc_ptr = cpu_to_le16(computed_crc);
312 }
313 
atsha204a_read(struct udevice * dev,enum atsha204a_zone zone,bool read32,u16 addr,u8 * buffer)314 int atsha204a_read(struct udevice *dev, enum atsha204a_zone zone, bool read32,
315 		  u16 addr, u8 *buffer)
316 {
317 	int res, retry = ATSHA204A_TRANSACTION_RETRY;
318 	struct atsha204a_req req;
319 	struct atsha204a_resp resp;
320 
321 	req.function = ATSHA204A_FUNC_COMMAND;
322 	req.length = 7;
323 	req.command = ATSHA204A_CMD_READ;
324 
325 	req.param1 = (u8) zone;
326 	if (read32)
327 		req.param1 |= 0x80;
328 
329 	req.param2 = cpu_to_le16(addr);
330 
331 	atsha204a_req_crc32(&req);
332 
333 	do {
334 		res = atsha204a_transaction(dev, &req, &resp);
335 		if (!res)
336 			break;
337 
338 		debug("ATSHA204A read retry (%d)\n", retry);
339 		retry--;
340 		atsha204a_wakeup(dev);
341 	} while (retry >= 0);
342 
343 	if (res) {
344 		debug("ATSHA204A read failed\n");
345 		return res;
346 	}
347 
348 	if (resp.length != (read32 ? 32 : 4) + 3) {
349 		debug("ATSHA204A read bad response length (%d)\n",
350 		      resp.length);
351 		return -EBADMSG;
352 	}
353 
354 	memcpy(buffer, ((u8 *) &resp) + 1, read32 ? 32 : 4);
355 
356 	return 0;
357 }
358 
atsha204a_get_random(struct udevice * dev,u8 * buffer,size_t max)359 int atsha204a_get_random(struct udevice *dev, u8 *buffer, size_t max)
360 {
361 	int res;
362 	struct atsha204a_req req;
363 	struct atsha204a_resp resp;
364 
365 	req.function = ATSHA204A_FUNC_COMMAND;
366 	req.length = 7;
367 	req.command = ATSHA204A_CMD_RANDOM;
368 
369 	req.param1 = 1;
370 	req.param2 = 0;
371 
372 	/* We do not have to compute the checksum dynamically */
373 	req.data[0] = 0x27;
374 	req.data[1] = 0x47;
375 
376 	res = atsha204a_transaction(dev, &req, &resp);
377 	if (res) {
378 		debug("ATSHA204A random transaction failed\n");
379 		return res;
380 	}
381 
382 	memcpy(buffer, ((u8 *) &resp) + 1, max >= 32 ? 32 : max);
383 	return 0;
384 }
385 
atsha204a_of_to_plat(struct udevice * dev)386 static int atsha204a_of_to_plat(struct udevice *dev)
387 {
388 	fdt_addr_t *priv = dev_get_priv(dev);
389 	fdt_addr_t addr;
390 
391 	addr = fdtdec_get_addr(gd->fdt_blob, dev_of_offset(dev), "reg");
392 	if (addr == FDT_ADDR_T_NONE) {
393 		debug("Can't get ATSHA204A I2C base address\n");
394 		return -ENXIO;
395 	}
396 
397 	*priv = addr;
398 	return 0;
399 }
400 
401 static const struct udevice_id atsha204a_ids[] = {
402 	{ .compatible = "atmel,atsha204a" },
403 	{ }
404 };
405 
406 U_BOOT_DRIVER(atsha204) = {
407 	.name			= "atsha204",
408 	.id			= UCLASS_MISC,
409 	.of_match		= atsha204a_ids,
410 	.of_to_plat	= atsha204a_of_to_plat,
411 	.priv_auto	= sizeof(fdt_addr_t),
412 };
413