]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/tpm/slb9635_i2c/tpm.c
Merge branch 'master' of git://git.denx.de/u-boot-arm
[karo-tx-uboot.git] / drivers / tpm / slb9635_i2c / tpm.c
1 /*
2  * Copyright (C) 2011 Infineon Technologies
3  *
4  * Authors:
5  * Peter Huewe <huewe.external@infineon.com>
6  *
7  * Description:
8  * Device driver for TCG/TCPA TPM (trusted platform module).
9  * Specifications at www.trustedcomputinggroup.org
10  *
11  * It is based on the Linux kernel driver tpm.c from Leendert van
12  * Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall.
13  *
14  * Version: 2.1.1
15  *
16  * See file CREDITS for list of people who contributed to this
17  * project.
18  *
19  * This program is free software; you can redistribute it and/or
20  * modify it under the terms of the GNU General Public License as
21  * published by the Free Software Foundation, version 2 of the
22  * License.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program; if not, write to the Free Software
31  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
32  * MA 02111-1307 USA
33  */
34
35 #include <malloc.h>
36 #include "tpm.h"
37
38 /* global structure for tpm chip data */
39 struct tpm_chip g_chip;
40
41 enum tpm_duration {
42         TPM_SHORT = 0,
43         TPM_MEDIUM = 1,
44         TPM_LONG = 2,
45         TPM_UNDEFINED,
46 };
47
48 #define TPM_MAX_ORDINAL 243
49 #define TPM_MAX_PROTECTED_ORDINAL 12
50 #define TPM_PROTECTED_ORDINAL_MASK 0xFF
51
52 /*
53  * Array with one entry per ordinal defining the maximum amount
54  * of time the chip could take to return the result.  The ordinal
55  * designation of short, medium or long is defined in a table in
56  * TCG Specification TPM Main Part 2 TPM Structures Section 17. The
57  * values of the SHORT, MEDIUM, and LONG durations are retrieved
58  * from the chip during initialization with a call to tpm_get_timeouts.
59  */
60 static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = {
61         TPM_UNDEFINED,          /* 0 */
62         TPM_UNDEFINED,
63         TPM_UNDEFINED,
64         TPM_UNDEFINED,
65         TPM_UNDEFINED,
66         TPM_UNDEFINED,          /* 5 */
67         TPM_UNDEFINED,
68         TPM_UNDEFINED,
69         TPM_UNDEFINED,
70         TPM_UNDEFINED,
71         TPM_SHORT,              /* 10 */
72         TPM_SHORT,
73 };
74
75 static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = {
76         TPM_UNDEFINED,          /* 0 */
77         TPM_UNDEFINED,
78         TPM_UNDEFINED,
79         TPM_UNDEFINED,
80         TPM_UNDEFINED,
81         TPM_UNDEFINED,          /* 5 */
82         TPM_UNDEFINED,
83         TPM_UNDEFINED,
84         TPM_UNDEFINED,
85         TPM_UNDEFINED,
86         TPM_SHORT,              /* 10 */
87         TPM_SHORT,
88         TPM_MEDIUM,
89         TPM_LONG,
90         TPM_LONG,
91         TPM_MEDIUM,             /* 15 */
92         TPM_SHORT,
93         TPM_SHORT,
94         TPM_MEDIUM,
95         TPM_LONG,
96         TPM_SHORT,              /* 20 */
97         TPM_SHORT,
98         TPM_MEDIUM,
99         TPM_MEDIUM,
100         TPM_MEDIUM,
101         TPM_SHORT,              /* 25 */
102         TPM_SHORT,
103         TPM_MEDIUM,
104         TPM_SHORT,
105         TPM_SHORT,
106         TPM_MEDIUM,             /* 30 */
107         TPM_LONG,
108         TPM_MEDIUM,
109         TPM_SHORT,
110         TPM_SHORT,
111         TPM_SHORT,              /* 35 */
112         TPM_MEDIUM,
113         TPM_MEDIUM,
114         TPM_UNDEFINED,
115         TPM_UNDEFINED,
116         TPM_MEDIUM,             /* 40 */
117         TPM_LONG,
118         TPM_MEDIUM,
119         TPM_SHORT,
120         TPM_SHORT,
121         TPM_SHORT,              /* 45 */
122         TPM_SHORT,
123         TPM_SHORT,
124         TPM_SHORT,
125         TPM_LONG,
126         TPM_MEDIUM,             /* 50 */
127         TPM_MEDIUM,
128         TPM_UNDEFINED,
129         TPM_UNDEFINED,
130         TPM_UNDEFINED,
131         TPM_UNDEFINED,          /* 55 */
132         TPM_UNDEFINED,
133         TPM_UNDEFINED,
134         TPM_UNDEFINED,
135         TPM_UNDEFINED,
136         TPM_MEDIUM,             /* 60 */
137         TPM_MEDIUM,
138         TPM_MEDIUM,
139         TPM_SHORT,
140         TPM_SHORT,
141         TPM_MEDIUM,             /* 65 */
142         TPM_UNDEFINED,
143         TPM_UNDEFINED,
144         TPM_UNDEFINED,
145         TPM_UNDEFINED,
146         TPM_SHORT,              /* 70 */
147         TPM_SHORT,
148         TPM_UNDEFINED,
149         TPM_UNDEFINED,
150         TPM_UNDEFINED,
151         TPM_UNDEFINED,          /* 75 */
152         TPM_UNDEFINED,
153         TPM_UNDEFINED,
154         TPM_UNDEFINED,
155         TPM_UNDEFINED,
156         TPM_LONG,               /* 80 */
157         TPM_UNDEFINED,
158         TPM_MEDIUM,
159         TPM_LONG,
160         TPM_SHORT,
161         TPM_UNDEFINED,          /* 85 */
162         TPM_UNDEFINED,
163         TPM_UNDEFINED,
164         TPM_UNDEFINED,
165         TPM_UNDEFINED,
166         TPM_SHORT,              /* 90 */
167         TPM_SHORT,
168         TPM_SHORT,
169         TPM_SHORT,
170         TPM_SHORT,
171         TPM_UNDEFINED,          /* 95 */
172         TPM_UNDEFINED,
173         TPM_UNDEFINED,
174         TPM_UNDEFINED,
175         TPM_UNDEFINED,
176         TPM_MEDIUM,             /* 100 */
177         TPM_SHORT,
178         TPM_SHORT,
179         TPM_UNDEFINED,
180         TPM_UNDEFINED,
181         TPM_UNDEFINED,          /* 105 */
182         TPM_UNDEFINED,
183         TPM_UNDEFINED,
184         TPM_UNDEFINED,
185         TPM_UNDEFINED,
186         TPM_SHORT,              /* 110 */
187         TPM_SHORT,
188         TPM_SHORT,
189         TPM_SHORT,
190         TPM_SHORT,
191         TPM_SHORT,              /* 115 */
192         TPM_SHORT,
193         TPM_SHORT,
194         TPM_UNDEFINED,
195         TPM_UNDEFINED,
196         TPM_LONG,               /* 120 */
197         TPM_LONG,
198         TPM_MEDIUM,
199         TPM_UNDEFINED,
200         TPM_SHORT,
201         TPM_SHORT,              /* 125 */
202         TPM_SHORT,
203         TPM_LONG,
204         TPM_SHORT,
205         TPM_SHORT,
206         TPM_SHORT,              /* 130 */
207         TPM_MEDIUM,
208         TPM_UNDEFINED,
209         TPM_SHORT,
210         TPM_MEDIUM,
211         TPM_UNDEFINED,          /* 135 */
212         TPM_UNDEFINED,
213         TPM_UNDEFINED,
214         TPM_UNDEFINED,
215         TPM_UNDEFINED,
216         TPM_SHORT,              /* 140 */
217         TPM_SHORT,
218         TPM_UNDEFINED,
219         TPM_UNDEFINED,
220         TPM_UNDEFINED,
221         TPM_UNDEFINED,          /* 145 */
222         TPM_UNDEFINED,
223         TPM_UNDEFINED,
224         TPM_UNDEFINED,
225         TPM_UNDEFINED,
226         TPM_SHORT,              /* 150 */
227         TPM_MEDIUM,
228         TPM_MEDIUM,
229         TPM_SHORT,
230         TPM_SHORT,
231         TPM_UNDEFINED,          /* 155 */
232         TPM_UNDEFINED,
233         TPM_UNDEFINED,
234         TPM_UNDEFINED,
235         TPM_UNDEFINED,
236         TPM_SHORT,              /* 160 */
237         TPM_SHORT,
238         TPM_SHORT,
239         TPM_SHORT,
240         TPM_UNDEFINED,
241         TPM_UNDEFINED,          /* 165 */
242         TPM_UNDEFINED,
243         TPM_UNDEFINED,
244         TPM_UNDEFINED,
245         TPM_UNDEFINED,
246         TPM_LONG,               /* 170 */
247         TPM_UNDEFINED,
248         TPM_UNDEFINED,
249         TPM_UNDEFINED,
250         TPM_UNDEFINED,
251         TPM_UNDEFINED,          /* 175 */
252         TPM_UNDEFINED,
253         TPM_UNDEFINED,
254         TPM_UNDEFINED,
255         TPM_UNDEFINED,
256         TPM_MEDIUM,             /* 180 */
257         TPM_SHORT,
258         TPM_MEDIUM,
259         TPM_MEDIUM,
260         TPM_MEDIUM,
261         TPM_MEDIUM,             /* 185 */
262         TPM_SHORT,
263         TPM_UNDEFINED,
264         TPM_UNDEFINED,
265         TPM_UNDEFINED,
266         TPM_UNDEFINED,          /* 190 */
267         TPM_UNDEFINED,
268         TPM_UNDEFINED,
269         TPM_UNDEFINED,
270         TPM_UNDEFINED,
271         TPM_UNDEFINED,          /* 195 */
272         TPM_UNDEFINED,
273         TPM_UNDEFINED,
274         TPM_UNDEFINED,
275         TPM_UNDEFINED,
276         TPM_SHORT,              /* 200 */
277         TPM_UNDEFINED,
278         TPM_UNDEFINED,
279         TPM_UNDEFINED,
280         TPM_SHORT,
281         TPM_SHORT,              /* 205 */
282         TPM_SHORT,
283         TPM_SHORT,
284         TPM_SHORT,
285         TPM_SHORT,
286         TPM_MEDIUM,             /* 210 */
287         TPM_UNDEFINED,
288         TPM_MEDIUM,
289         TPM_MEDIUM,
290         TPM_MEDIUM,
291         TPM_UNDEFINED,          /* 215 */
292         TPM_MEDIUM,
293         TPM_UNDEFINED,
294         TPM_UNDEFINED,
295         TPM_SHORT,
296         TPM_SHORT,              /* 220 */
297         TPM_SHORT,
298         TPM_SHORT,
299         TPM_SHORT,
300         TPM_SHORT,
301         TPM_UNDEFINED,          /* 225 */
302         TPM_UNDEFINED,
303         TPM_UNDEFINED,
304         TPM_UNDEFINED,
305         TPM_UNDEFINED,
306         TPM_SHORT,              /* 230 */
307         TPM_LONG,
308         TPM_MEDIUM,
309         TPM_UNDEFINED,
310         TPM_UNDEFINED,
311         TPM_UNDEFINED,          /* 235 */
312         TPM_UNDEFINED,
313         TPM_UNDEFINED,
314         TPM_UNDEFINED,
315         TPM_UNDEFINED,
316         TPM_SHORT,              /* 240 */
317         TPM_UNDEFINED,
318         TPM_MEDIUM,
319 };
320
321 /*
322  * Returns max number of milliseconds to wait
323  */
324 unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
325 {
326         int duration_idx = TPM_UNDEFINED;
327         int duration = 0;
328
329         if (ordinal < TPM_MAX_ORDINAL)
330                 duration_idx = tpm_ordinal_duration[ordinal];
331         else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) <
332                  TPM_MAX_PROTECTED_ORDINAL)
333                 duration_idx =
334                     tpm_protected_ordinal_duration[ordinal &
335                                                    TPM_PROTECTED_ORDINAL_MASK];
336
337         if (duration_idx != TPM_UNDEFINED)
338                 duration = chip->vendor.duration[duration_idx];
339         if (duration <= 0)
340                 return 2 * 60 * HZ; /*two minutes timeout*/
341         else
342                 return duration;
343 }
344
345 #define TPM_CMD_COUNT_BYTE 2
346 #define TPM_CMD_ORDINAL_BYTE 6
347
348 ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz)
349 {
350         ssize_t rc;
351         u32 count, ordinal;
352         unsigned long start, stop;
353
354         struct tpm_chip *chip = &g_chip;
355
356         /* switch endianess: big->little */
357         count = get_unaligned_be32(buf + TPM_CMD_COUNT_BYTE);
358         ordinal = get_unaligned_be32(buf + TPM_CMD_ORDINAL_BYTE);
359
360         if (count == 0) {
361                 dev_err(chip->dev, "no data\n");
362                 return -ENODATA;
363         }
364         if (count > bufsiz) {
365                 dev_err(chip->dev,
366                         "invalid count value %x %zx\n", count, bufsiz);
367                 return -E2BIG;
368         }
369
370         rc = chip->vendor.send(chip, (u8 *)buf, count);
371         if (rc < 0) {
372                 dev_err(chip->dev, "tpm_transmit: tpm_send: error %zd\n", rc);
373                 goto out;
374         }
375
376         if (chip->vendor.irq)
377                 goto out_recv;
378
379         start = get_timer(0);
380         stop = tpm_calc_ordinal_duration(chip, ordinal);
381         do {
382                 dbg_printf("waiting for status...\n");
383                 u8 status = chip->vendor.status(chip);
384                 if ((status & chip->vendor.req_complete_mask) ==
385                     chip->vendor.req_complete_val) {
386                         dbg_printf("...got it;\n");
387                         goto out_recv;
388                 }
389
390                 if ((status == chip->vendor.req_canceled)) {
391                         dev_err(chip->dev, "Operation Canceled\n");
392                         rc = -ECANCELED;
393                         goto out;
394                 }
395                 msleep(TPM_TIMEOUT);
396         } while (get_timer(start) < stop);
397
398         chip->vendor.cancel(chip);
399         dev_err(chip->dev, "Operation Timed out\n");
400         rc = -ETIME;
401         goto out;
402
403 out_recv:
404
405         dbg_printf("out_recv: reading response...\n");
406         rc = chip->vendor.recv(chip, (u8 *)buf, TPM_BUFSIZE);
407         if (rc < 0)
408                 dev_err(chip->dev, "tpm_transmit: tpm_recv: error %zd\n", rc);
409 out:
410         return rc;
411 }
412
413 #define TPM_ERROR_SIZE 10
414
415 enum tpm_capabilities {
416         TPM_CAP_PROP = cpu_to_be32(5),
417 };
418
419 enum tpm_sub_capabilities {
420         TPM_CAP_PROP_TIS_TIMEOUT = cpu_to_be32(0x115),
421         TPM_CAP_PROP_TIS_DURATION = cpu_to_be32(0x120),
422 };
423
424 struct tpm_chip *tpm_register_hardware(const struct tpm_vendor_specific *entry)
425 {
426         struct tpm_chip *chip;
427
428         /* Driver specific per-device data */
429         chip = &g_chip;
430         memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific));
431         chip->is_open = 1;
432
433         return chip;
434 }
435
436 int tpm_open(uint32_t dev_addr)
437 {
438         int rc;
439         if (g_chip.is_open)
440                 return -EBUSY;
441         rc = tpm_vendor_init(dev_addr);
442         if (rc < 0)
443                 g_chip.is_open = 0;
444         return rc;
445 }
446
447 void tpm_close(void)
448 {
449         if (g_chip.is_open) {
450                 tpm_vendor_cleanup(&g_chip);
451                 g_chip.is_open = 0;
452         }
453 }