Merge tag 'efi-2022-07-rc1-2' of https://source.denx.de/u-boot/custodians/u-boot-efi
[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 <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
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
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 crc;
150 }
151
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
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
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
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                 return 0;
244         }
245
246         return -ETIMEDOUT;
247 }
248
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
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
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                 udelay(ATSHA204A_EXECTIME);
284                 res = atsha204a_recv_resp(dev, resp);
285                 if (!res || res == -EMSGSIZE || res == -EBADMSG)
286                         break;
287
288                 debug("ATSHA204A transaction polling for response "
289                       "(timeout = %d)\n", timeout);
290
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
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
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
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
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 = dev_read_addr(dev);
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 };