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