2 * I2C Driver for Atmel ATSHA204 over I2C
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
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.
17 #include <atsha204a-i2c.h>
19 #include <asm/global_data.h>
20 #include <linux/delay.h>
21 #include <u-boot/crc.h>
23 #define ATSHA204A_TWLO 60
24 #define ATSHA204A_TRANSACTION_TIMEOUT 100000
25 #define ATSHA204A_TRANSACTION_RETRY 5
26 #define ATSHA204A_EXECTIME 5000
28 DECLARE_GLOBAL_DATA_PTR;
31 * The ATSHA204A uses an (to me) unknown CRC-16 algorithm.
32 * The Reveng CRC-16 catalogue does not contain it.
34 * Because in Atmel's documentation only a primitive implementation
35 * can be found, I have implemented this one with lookup table.
39 * This is the code that computes the table below:
42 * for (i = 0; i < 256; ++i) {
44 * for (j = 0; j < 8; ++j) {
45 * c = (c << 1) | ((i >> j) & 1);
47 * bitreverse_table[i] = c;
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,
87 * This is the code that computes the table below:
90 * for (i = 0; i < 256; ++i) {
92 * for (j = 0; j < 8; ++j) {
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,
136 static inline u16 crc16_byte(u16 crc, const u8 data)
138 u16 t = crc16_table[((crc >> 8) ^ bitreverse_table[data]) & 0xff];
139 return ((crc << 8) ^ t);
142 static u16 atsha204a_crc16(const u8 *buffer, size_t len)
147 crc = crc16_byte(crc, *buffer++);
149 return cpu_to_le16(crc);
152 static int atsha204a_send(struct udevice *dev, const u8 *buf, u8 len)
154 fdt_addr_t *priv = dev_get_priv(dev);
158 msg.flags = I2C_M_STOP;
160 msg.buf = (u8 *) buf;
162 return dm_i2c_xfer(dev, &msg, 1);
165 static int atsha204a_recv(struct udevice *dev, u8 *buf, u8 len)
167 fdt_addr_t *priv = dev_get_priv(dev);
171 msg.flags = I2C_M_RD | I2C_M_STOP;
173 msg.buf = (u8 *) buf;
175 return dm_i2c_xfer(dev, &msg, 1);
178 static int atsha204a_recv_resp(struct udevice *dev,
179 struct atsha204a_resp *resp)
182 u16 resp_crc, computed_crc;
185 res = atsha204a_recv(dev, p, 4);
189 if (resp->length > 4) {
190 if (resp->length > sizeof(*resp))
193 res = atsha204a_recv(dev, p + 4, resp->length - 4);
198 resp_crc = (u16) p[resp->length - 2]
199 | (((u16) p[resp->length - 1]) << 8);
200 computed_crc = atsha204a_crc16(p, resp->length - 2);
202 if (resp_crc != computed_crc) {
203 debug("Invalid checksum in ATSHA204A response\n");
210 int atsha204a_wakeup(struct udevice *dev)
213 struct atsha204a_resp resp;
216 debug("Waking up ATSHA204A\n");
218 for (try = 1; try <= 10; ++try) {
219 debug("Try %i... ", try);
222 res = atsha204a_send(dev, req, 4);
224 debug("failed on I2C send, trying again\n");
228 udelay(ATSHA204A_TWLO);
230 res = atsha204a_recv_resp(dev, &resp);
232 debug("failed on receiving response, ending\n");
236 if (resp.code != ATSHA204A_STATUS_AFTER_WAKE) {
237 debug ("failed (responce code = %02x), ending\n",
249 int atsha204a_idle(struct udevice *dev)
252 u8 req = ATSHA204A_FUNC_IDLE;
254 res = atsha204a_send(dev, &req, 1);
256 debug("Failed putting ATSHA204A idle\n");
260 int atsha204a_sleep(struct udevice *dev)
263 u8 req = ATSHA204A_FUNC_IDLE;
265 res = atsha204a_send(dev, &req, 1);
267 debug("Failed putting ATSHA204A to sleep\n");
271 static int atsha204a_transaction(struct udevice *dev, struct atsha204a_req *req,
272 struct atsha204a_resp *resp)
274 int res, timeout = ATSHA204A_TRANSACTION_TIMEOUT;
276 res = atsha204a_send(dev, (u8 *) req, req->length + 1);
278 debug("ATSHA204A transaction send failed\n");
283 res = atsha204a_recv_resp(dev, resp);
284 if (!res || res == -EMSGSIZE || res == -EBADMSG)
287 debug("ATSHA204A transaction polling for response "
288 "(timeout = %d)\n", timeout);
290 udelay(ATSHA204A_EXECTIME);
291 timeout -= ATSHA204A_EXECTIME;
292 } while (timeout > 0);
295 debug("ATSHA204A transaction timed out\n");
302 static void atsha204a_req_crc32(struct atsha204a_req *req)
306 u16 *crc_ptr = (u16 *) &p[req->length - 1];
308 /* The buffer to crc16 starts at byte 1, not 0 */
309 computed_crc = atsha204a_crc16(p + 1, req->length - 2);
311 *crc_ptr = cpu_to_le16(computed_crc);
314 int atsha204a_read(struct udevice *dev, enum atsha204a_zone zone, bool read32,
315 u16 addr, u8 *buffer)
317 int res, retry = ATSHA204A_TRANSACTION_RETRY;
318 struct atsha204a_req req;
319 struct atsha204a_resp resp;
321 req.function = ATSHA204A_FUNC_COMMAND;
323 req.command = ATSHA204A_CMD_READ;
325 req.param1 = (u8) zone;
329 req.param2 = cpu_to_le16(addr);
331 atsha204a_req_crc32(&req);
334 res = atsha204a_transaction(dev, &req, &resp);
338 debug("ATSHA204A read retry (%d)\n", retry);
340 atsha204a_wakeup(dev);
341 } while (retry >= 0);
344 debug("ATSHA204A read failed\n");
348 if (resp.length != (read32 ? 32 : 4) + 3) {
349 debug("ATSHA204A read bad response length (%d)\n",
354 memcpy(buffer, ((u8 *) &resp) + 1, read32 ? 32 : 4);
359 int atsha204a_get_random(struct udevice *dev, u8 *buffer, size_t max)
362 struct atsha204a_req req;
363 struct atsha204a_resp resp;
365 req.function = ATSHA204A_FUNC_COMMAND;
367 req.command = ATSHA204A_CMD_RANDOM;
372 /* We do not have to compute the checksum dynamically */
376 res = atsha204a_transaction(dev, &req, &resp);
378 debug("ATSHA204A random transaction failed\n");
382 memcpy(buffer, ((u8 *) &resp) + 1, max >= 32 ? 32 : max);
386 static int atsha204a_of_to_plat(struct udevice *dev)
388 fdt_addr_t *priv = dev_get_priv(dev);
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");
401 static const struct udevice_id atsha204a_ids[] = {
402 { .compatible = "atmel,atsha204a" },
406 U_BOOT_DRIVER(atsha204) = {
409 .of_match = atsha204a_ids,
410 .of_to_plat = atsha204a_of_to_plat,
411 .priv_auto = sizeof(fdt_addr_t),