1/* $NetBSD: tpm.c,v 1.11 2014/07/25 08:10:37 dholland Exp $ */
2/*
3 * Copyright (c) 2008, 2009 Michael Shalayeff
4 * Copyright (c) 2009, 2010 Hans-Jörg Höxer
5 * All rights reserved.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
16 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <sys/cdefs.h>
21__KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.11 2014/07/25 08:10:37 dholland Exp $");
22
23#if 0
24#define TPM_DEBUG
25#define aprint_debug_dev aprint_error_dev
26#endif
27
28#include <sys/param.h>
29#include <sys/systm.h>
30#include <sys/kernel.h>
31#include <sys/malloc.h>
32#include <sys/proc.h>
33#include <sys/device.h>
34#include <sys/conf.h>
35#include <sys/bus.h>
36#include <sys/pmf.h>
37
38#include <dev/ic/tpmreg.h>
39#include <dev/ic/tpmvar.h>
40
41/* Set when enabling legacy interface in host bridge. */
42int tpm_enabled;
43
44const struct {
45 uint32_t devid;
46 char name[32];
47 int flags;
48#define TPM_DEV_NOINTS 0x0001
49} tpm_devs[] = {
50 { 0x000615d1, "IFX SLD 9630 TT 1.1", 0 },
51 { 0x000b15d1, "IFX SLB 9635 TT 1.2", 0 },
52 { 0x100214e4, "Broadcom BCM0102", TPM_DEV_NOINTS },
53 { 0x00fe1050, "WEC WPCT200", 0 },
54 { 0x687119fa, "SNS SSX35", 0 },
55 { 0x2e4d5453, "STM ST19WP18", 0 },
56 { 0x32021114, "ATML 97SC3203", TPM_DEV_NOINTS },
57 { 0x10408086, "INTEL INTC0102", 0 },
58 { 0, "", TPM_DEV_NOINTS },
59};
60
61int tpm_tis12_irqinit(struct tpm_softc *, int, int);
62
63int tpm_waitfor_poll(struct tpm_softc *, uint8_t, int, void *);
64int tpm_waitfor_int(struct tpm_softc *, uint8_t, int, void *, int);
65int tpm_waitfor(struct tpm_softc *, uint8_t, int, void *);
66int tpm_request_locality(struct tpm_softc *, int);
67int tpm_getburst(struct tpm_softc *);
68uint8_t tpm_status(struct tpm_softc *);
69int tpm_tmotohz(int);
70
71static dev_type_open(tpmopen);
72static dev_type_close(tpmclose);
73static dev_type_read(tpmread);
74static dev_type_read(tpmwrite);
75static dev_type_ioctl(tpmioctl);
76
77extern struct cfdriver tpm_cd;
78#define TPMUNIT(a) minor(a)
79
80const struct cdevsw tpm_cdevsw = {
81 .d_open = tpmopen,
82 .d_close = tpmclose,
83 .d_read = tpmread,
84 .d_write = tpmwrite,
85 .d_ioctl = tpmioctl,
86 .d_stop = nostop,
87 .d_tty = notty,
88 .d_poll = nopoll,
89 .d_mmap = nommap,
90 .d_kqfilter = nokqfilter,
91 .d_discard = nodiscard,
92 .d_flag = D_OTHER,
93};
94
95/* Probe TPM using TIS 1.2 interface. */
96int
97tpm_tis12_probe(bus_space_tag_t bt, bus_space_handle_t bh)
98{
99 uint32_t r;
100 uint8_t save, reg;
101
102 r = bus_space_read_4(bt, bh, TPM_INTF_CAPABILITIES);
103 if (r == 0xffffffff)
104 return 0;
105
106#ifdef TPM_DEBUG
107 char buf[128];
108 snprintb(buf, sizeof(buf), TPM_CAPBITS, r);
109 printf("%s: caps=%s\n", __func__, buf);
110#endif
111 if ((r & TPM_CAPSREQ) != TPM_CAPSREQ ||
112 !(r & (TPM_INTF_INT_EDGE_RISING | TPM_INTF_INT_LEVEL_LOW))) {
113#ifdef TPM_DEBUG
114 printf("%s: caps too low (caps=%s)\n", __func__, buf);
115#endif
116 return 0;
117 }
118
119 save = bus_space_read_1(bt, bh, TPM_ACCESS);
120 bus_space_write_1(bt, bh, TPM_ACCESS, TPM_ACCESS_REQUEST_USE);
121 reg = bus_space_read_1(bt, bh, TPM_ACCESS);
122 if ((reg & TPM_ACCESS_VALID) && (reg & TPM_ACCESS_ACTIVE_LOCALITY) &&
123 bus_space_read_4(bt, bh, TPM_ID) != 0xffffffff)
124 return 1;
125
126 bus_space_write_1(bt, bh, TPM_ACCESS, save);
127 return 0;
128}
129
130/*
131 * Setup interrupt vector if one is provided and interrupts are know to
132 * work on that particular chip.
133 */
134int
135tpm_tis12_irqinit(struct tpm_softc *sc, int irq, int idx)
136{
137 uint32_t r;
138
139 if ((irq == -1) || (tpm_devs[idx].flags & TPM_DEV_NOINTS)) {
140 sc->sc_vector = -1;
141 return 0;
142 }
143
144 /* Ack and disable all interrupts. */
145 r = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INTERRUPT_ENABLE);
146 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INTERRUPT_ENABLE,
147 r & ~TPM_GLOBAL_INT_ENABLE);
148 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS,
149 bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS));
150#ifdef TPM_DEBUG
151 char buf[128];
152 snprintb(buf, sizeof(buf), TPM_INTERRUPT_ENABLE_BITS, r);
153 aprint_debug_dev(sc->sc_dev, "%s: before ien %s\n", __func__, buf);
154#endif
155
156 /* Program interrupt vector. */
157 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_INT_VECTOR, irq);
158 sc->sc_vector = irq;
159
160 /* Program interrupt type. */
161 r &= ~(TPM_INT_EDGE_RISING|TPM_INT_EDGE_FALLING|TPM_INT_LEVEL_HIGH|
162 TPM_INT_LEVEL_LOW);
163 r |= TPM_GLOBAL_INT_ENABLE|TPM_CMD_READY_INT|TPM_LOCALITY_CHANGE_INT|
164 TPM_STS_VALID_INT|TPM_DATA_AVAIL_INT;
165 if (sc->sc_capabilities & TPM_INTF_INT_EDGE_RISING)
166 r |= TPM_INT_EDGE_RISING;
167 else if (sc->sc_capabilities & TPM_INTF_INT_EDGE_FALLING)
168 r |= TPM_INT_EDGE_FALLING;
169 else if (sc->sc_capabilities & TPM_INTF_INT_LEVEL_HIGH)
170 r |= TPM_INT_LEVEL_HIGH;
171 else
172 r |= TPM_INT_LEVEL_LOW;
173
174 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INTERRUPT_ENABLE, r);
175#ifdef TPM_DEBUG
176 snprintb(buf, sizeof(buf), TPM_INTERRUPT_ENABLE_BITS, r);
177 aprint_debug_dev(sc->sc_dev, "%s: after ien %s\n", __func__, buf);
178#endif
179
180 return 0;
181}
182
183/* Setup TPM using TIS 1.2 interface. */
184int
185tpm_tis12_init(struct tpm_softc *sc, int irq, const char *name)
186{
187 uint32_t r;
188 int i;
189
190 r = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INTF_CAPABILITIES);
191#ifdef TPM_DEBUG
192 char cbuf[128];
193 snprintb(cbuf, sizeof(cbuf), TPM_CAPBITS, r);
194 aprint_debug_dev(sc->sc_dev, "%s: caps=%s ", __func__, cbuf);
195#endif
196 if ((r & TPM_CAPSREQ) != TPM_CAPSREQ ||
197 !(r & (TPM_INTF_INT_EDGE_RISING | TPM_INTF_INT_LEVEL_LOW))) {
198 char buf[128];
199 snprintb(buf, sizeof(buf), TPM_CAPBITS, r);
200 aprint_error_dev(sc->sc_dev, "capabilities too low (caps=%s)\n",
201 buf);
202 return 1;
203 }
204 sc->sc_capabilities = r;
205
206 sc->sc_devid = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_ID);
207 sc->sc_rev = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_REV);
208
209 for (i = 0; tpm_devs[i].devid; i++)
210 if (tpm_devs[i].devid == sc->sc_devid)
211 break;
212
213 if (tpm_devs[i].devid)
214 aprint_normal(": %s rev 0x%x\n",
215 tpm_devs[i].name, sc->sc_rev);
216 else
217 aprint_normal(": device 0x%08x rev 0x%x\n",
218 sc->sc_devid, sc->sc_rev);
219
220 if (tpm_tis12_irqinit(sc, irq, i))
221 return 1;
222
223 if (tpm_request_locality(sc, 0))
224 return 1;
225
226 /* Abort whatever it thought it was doing. */
227 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS, TPM_STS_CMD_READY);
228
229 return 0;
230}
231
232int
233tpm_request_locality(struct tpm_softc *sc, int l)
234{
235 uint32_t r;
236 int to, rv;
237
238 if (l != 0)
239 return EINVAL;
240
241 if ((bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS) &
242 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) ==
243 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY))
244 return 0;
245
246 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS,
247 TPM_ACCESS_REQUEST_USE);
248
249 to = tpm_tmotohz(TPM_ACCESS_TMO);
250
251 while ((r = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS) &
252 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
253 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY) && to--) {
254 rv = tsleep(sc->sc_init, PRIBIO | PCATCH, "tpm_locality", 1);
255 if (rv && rv != EWOULDBLOCK) {
256#ifdef TPM_DEBUG
257 aprint_debug_dev(sc->sc_dev, "%s: interrupted %d\n",
258 __func__, rv);
259#endif
260 return rv;
261 }
262 }
263
264 if ((r & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
265 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) {
266#ifdef TPM_DEBUG
267 char buf[128];
268 snprintb(buf, sizeof(buf), TPM_ACCESS_BITS, r);
269 aprint_debug_dev(sc->sc_dev, "%s: access %s\n", __func__, buf);
270#endif
271 return EBUSY;
272 }
273
274 return 0;
275}
276
277int
278tpm_getburst(struct tpm_softc *sc)
279{
280 int burst, to, rv;
281
282 to = tpm_tmotohz(TPM_BURST_TMO);
283
284 burst = 0;
285 while (burst == 0 && to--) {
286 /*
287 * Burst count has to be read from bits 8 to 23 without
288 * touching any other bits, eg. the actual status bits 0
289 * to 7.
290 */
291 burst = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_STS + 1);
292 burst |= bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_STS + 2)
293 << 8;
294#ifdef TPM_DEBUG
295 aprint_debug_dev(sc->sc_dev, "%s: read %d\n", __func__, burst);
296#endif
297 if (burst)
298 return burst;
299
300 rv = tsleep(sc, PRIBIO | PCATCH, "tpm_getburst", 1);
301 if (rv && rv != EWOULDBLOCK) {
302 return 0;
303 }
304 }
305
306 return 0;
307}
308
309uint8_t
310tpm_status(struct tpm_softc *sc)
311{
312 return bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_STS) & TPM_STS_MASK;
313}
314
315int
316tpm_tmotohz(int tmo)
317{
318 struct timeval tv;
319
320 tv.tv_sec = tmo / 1000;
321 tv.tv_usec = 1000 * (tmo % 1000);
322
323 return tvtohz(&tv);
324}
325
326/* Save TPM state on suspend. */
327bool
328tpm_suspend(device_t dev, const pmf_qual_t *qual)
329{
330 struct tpm_softc *sc = device_private(dev);
331 static const uint8_t command[] = {
332 0, 193, /* TPM_TAG_RQU_COMMAND */
333 0, 0, 0, 10, /* Length in bytes */
334 0, 0, 0, 156 /* TPM_ORD_SaveStates */
335 };
336 uint8_t scratch[sizeof(command)];
337
338 /*
339 * Power down: We have to issue the SaveStates command.
340 */
341 (*sc->sc_write)(sc, &command, sizeof(command));
342 (*sc->sc_read)(sc, &scratch, sizeof(scratch), NULL, TPM_HDRSIZE);
343#ifdef TPM_DEBUG
344 aprint_debug_dev(sc->sc_dev, "%s: power down\n", __func__);
345#endif
346 return true;
347}
348
349/*
350 * Handle resume event. Actually nothing to do as the BIOS is supposed
351 * to restore the previously saved state.
352 */
353bool
354tpm_resume(device_t dev, const pmf_qual_t *qual)
355{
356#ifdef TPM_DEBUG
357 struct tpm_softc *sc = device_private(dev);
358 aprint_debug_dev(sc->sc_dev, "%s: resume\n", __func__);
359#endif
360 return true;
361}
362
363/* Wait for given status bits using polling. */
364int
365tpm_waitfor_poll(struct tpm_softc *sc, uint8_t mask, int tmo, void *c)
366{
367 int rv;
368
369 /*
370 * Poll until either the requested condition or a time out is
371 * met.
372 */
373 while (((sc->sc_stat = tpm_status(sc)) & mask) != mask && tmo--) {
374 rv = tsleep(c, PRIBIO | PCATCH, "tpm_poll", 1);
375 if (rv && rv != EWOULDBLOCK) {
376#ifdef TPM_DEBUG
377 aprint_debug_dev(sc->sc_dev,
378 "%s: interrupted %d\n", __func__, rv);
379#endif
380 return rv;
381 }
382 }
383
384 return 0;
385}
386
387/* Wait for given status bits using interrupts. */
388int
389tpm_waitfor_int(struct tpm_softc *sc, uint8_t mask, int tmo, void *c,
390 int inttype)
391{
392 int rv, to;
393
394 /* Poll and return when condition is already met. */
395 sc->sc_stat = tpm_status(sc);
396 if ((sc->sc_stat & mask) == mask)
397 return 0;
398
399 /*
400 * Enable interrupt on tpm chip. Note that interrupts on our
401 * level (SPL_TTY) are disabled (see tpm{read,write} et al) and
402 * will not be delivered to the cpu until we call tsleep(9) below.
403 */
404 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INTERRUPT_ENABLE,
405 bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INTERRUPT_ENABLE) |
406 inttype);
407 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INTERRUPT_ENABLE,
408 bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INTERRUPT_ENABLE) |
409 TPM_GLOBAL_INT_ENABLE);
410
411 /*
412 * Poll once more to remedy the race between previous polling
413 * and enabling interrupts on the tpm chip.
414 */
415 sc->sc_stat = tpm_status(sc);
416 if ((sc->sc_stat & mask) == mask) {
417 rv = 0;
418 goto out;
419 }
420
421 to = tpm_tmotohz(tmo);
422#ifdef TPM_DEBUG
423 aprint_debug_dev(sc->sc_dev,
424 "%s: sleeping for %d ticks on %p\n", __func__, to, c);
425#endif
426 /*
427 * tsleep(9) enables interrupts on the cpu and returns after
428 * wake up with interrupts disabled again. Note that interrupts
429 * generated by the tpm chip while being at SPL_TTY are not lost
430 * but held and delivered as soon as the cpu goes below SPL_TTY.
431 */
432 rv = tsleep(c, PRIBIO | PCATCH, "tpm_wait", to);
433
434 sc->sc_stat = tpm_status(sc);
435#ifdef TPM_DEBUG
436 char buf[128];
437 snprintb(buf, sizeof(buf), TPM_STS_BITS, sc->sc_stat);
438 aprint_debug_dev(sc->sc_dev,
439 "%s: woke up with rv %d stat %s\n", __func__, rv, buf);
440#endif
441 if ((sc->sc_stat & mask) == mask)
442 rv = 0;
443
444 /* Disable interrupts on tpm chip again. */
445out: bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INTERRUPT_ENABLE,
446 bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INTERRUPT_ENABLE) &
447 ~TPM_GLOBAL_INT_ENABLE);
448 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INTERRUPT_ENABLE,
449 bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INTERRUPT_ENABLE) &
450 ~inttype);
451
452 return rv;
453}
454
455/*
456 * Wait on given status bits, uses interrupts where possible, otherwise polls.
457 */
458int
459tpm_waitfor(struct tpm_softc *sc, uint8_t b0, int tmo, void *c)
460{
461 uint8_t b;
462 int re, to, rv;
463
464#ifdef TPM_DEBUG
465 char buf[128];
466 snprintb(buf, sizeof(buf), TPM_STS_BITS, sc->sc_stat);
467 aprint_debug_dev(sc->sc_dev, "%s: b0 %s\n", __func__, buf);
468#endif
469
470 /*
471 * If possible, use interrupts, otherwise poll.
472 *
473 * We use interrupts for TPM_STS_VALID and TPM_STS_DATA_AVAIL (if
474 * the tpm chips supports them) as waiting for those can take
475 * really long. The other TPM_STS* are not needed very often
476 * so we do not support them.
477 */
478 if (sc->sc_vector != -1) {
479 b = b0;
480
481 /*
482 * Wait for data ready. This interrupt only occures
483 * when both TPM_STS_VALID and TPM_STS_DATA_AVAIL are asserted.
484 * Thus we don't have to bother with TPM_STS_VALID
485 * separately and can just return.
486 *
487 * This only holds for interrupts! When using polling
488 * both flags have to be waited for, see below.
489 */
490 if ((b & TPM_STS_DATA_AVAIL) && (sc->sc_capabilities &
491 TPM_INTF_DATA_AVAIL_INT))
492 return tpm_waitfor_int(sc, b, tmo, c,
493 TPM_DATA_AVAIL_INT);
494
495 /* Wait for status valid bit. */
496 if ((b & TPM_STS_VALID) && (sc->sc_capabilities &
497 TPM_INTF_STS_VALID_INT)) {
498 rv = tpm_waitfor_int(sc, b, tmo, c, TPM_STS_VALID_INT);
499 if (rv != 0)
500 return rv;
501 else
502 b = b0 & ~TPM_STS_VALID;
503 }
504
505 /*
506 * When all flags are taken care of, return. Otherwise
507 * use polling for eg. TPM_STS_CMD_READY.
508 */
509 if (b == 0)
510 return 0;
511 }
512
513 re = 3;
514restart:
515 /*
516 * If requested wait for TPM_STS_VALID before dealing with
517 * any other flag. Eg. when both TPM_STS_DATA_AVAIL and TPM_STS_VALID
518 * are requested, wait for the latter first.
519 */
520 b = b0;
521 if (b0 & TPM_STS_VALID)
522 b = TPM_STS_VALID;
523
524 to = tpm_tmotohz(tmo);
525again:
526 if ((rv = tpm_waitfor_poll(sc, b, to, c)) != 0)
527 return rv;
528
529 if ((b & sc->sc_stat) == TPM_STS_VALID) {
530 /* Now wait for other flags. */
531 b = b0 & ~TPM_STS_VALID;
532 to++;
533 goto again;
534 }
535
536 if ((sc->sc_stat & b) != b) {
537#ifdef TPM_DEBUG
538 char bbuf[128], cbuf[128];
539 snprintb(bbuf, sizeof(bbuf), TPM_STS_BITS, b);
540 snprintb(cbuf, sizeof(cbuf), TPM_STS_BITS, sc->sc_stat);
541 aprint_debug_dev(sc->sc_dev,
542 "%s: timeout: stat=%s b=%s\n", __func__, cbuf, bbuf);
543#endif
544 if (re-- && (b0 & TPM_STS_VALID)) {
545 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS,
546 TPM_STS_RESP_RETRY);
547 goto restart;
548 }
549 return EIO;
550 }
551
552 return 0;
553}
554
555/* Start transaction. */
556int
557tpm_tis12_start(struct tpm_softc *sc, int flag)
558{
559 int rv;
560
561 if (flag == UIO_READ) {
562 rv = tpm_waitfor(sc, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
563 TPM_READ_TMO, sc->sc_read);
564 return rv;
565 }
566
567 /* Own our (0th) locality. */
568 if ((rv = tpm_request_locality(sc, 0)) != 0)
569 return rv;
570
571 sc->sc_stat = tpm_status(sc);
572 if (sc->sc_stat & TPM_STS_CMD_READY) {
573#ifdef TPM_DEBUG
574 char buf[128];
575 snprintb(buf, sizeof(buf), TPM_STS_BITS, sc->sc_stat);
576 aprint_debug_dev(sc->sc_dev, "%s: UIO_WRITE status %s\n",
577 __func__, buf);
578#endif
579 return 0;
580 }
581
582#ifdef TPM_DEBUG
583 aprint_debug_dev(sc->sc_dev,
584 "%s: UIO_WRITE readying chip\n", __func__);
585#endif
586
587 /* Abort previous and restart. */
588 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS, TPM_STS_CMD_READY);
589 if ((rv = tpm_waitfor(sc, TPM_STS_CMD_READY, TPM_READY_TMO,
590 sc->sc_write))) {
591#ifdef TPM_DEBUG
592 aprint_debug_dev(sc->sc_dev,
593 "%s: UIO_WRITE readying failed %d\n", __func__, rv);
594#endif
595 return rv;
596 }
597
598#ifdef TPM_DEBUG
599 aprint_debug_dev(sc->sc_dev,
600 "%s: UIO_WRITE readying done\n", __func__);
601#endif
602
603 return 0;
604}
605
606int
607tpm_tis12_read(struct tpm_softc *sc, void *buf, size_t len, size_t *count,
608 int flags)
609{
610 uint8_t *p = buf;
611 size_t cnt;
612 int rv, n, bcnt;
613
614#ifdef TPM_DEBUG
615 aprint_debug_dev(sc->sc_dev, "%s: len %zu\n", __func__, len);
616#endif
617 cnt = 0;
618 while (len > 0) {
619 if ((rv = tpm_waitfor(sc, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
620 TPM_READ_TMO, sc->sc_read)))
621 return rv;
622
623 bcnt = tpm_getburst(sc);
624 n = MIN(len, bcnt);
625#ifdef TPM_DEBUG
626 aprint_debug_dev(sc->sc_dev,
627 "%s: fetching %d, burst is %d\n", __func__, n, bcnt);
628#endif
629 for (; n--; len--) {
630 *p++ = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_DATA);
631 cnt++;
632 }
633
634 if ((flags & TPM_PARAM_SIZE) == 0 && cnt >= 6)
635 break;
636 }
637#ifdef TPM_DEBUG
638 aprint_debug_dev(sc->sc_dev,
639 "%s: read %zu bytes, len %zu\n", __func__, cnt, len);
640#endif
641
642 if (count)
643 *count = cnt;
644
645 return 0;
646}
647
648int
649tpm_tis12_write(struct tpm_softc *sc, const void *buf, size_t len)
650{
651 const uint8_t *p = buf;
652 size_t cnt;
653 int rv, r;
654
655#ifdef TPM_DEBUG
656 aprint_debug_dev(sc->sc_dev,
657 "%s: sc %p buf %p len %zu\n", __func__, sc, buf, len);
658#endif
659 if (len == 0)
660 return 0;
661
662 if ((rv = tpm_request_locality(sc, 0)) != 0)
663 return rv;
664
665 cnt = 0;
666 while (cnt < len - 1) {
667 for (r = tpm_getburst(sc); r > 0 && cnt < len - 1; r--) {
668 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_DATA, *p++);
669 cnt++;
670 }
671 if ((rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, sc))) {
672#ifdef TPM_DEBUG
673 aprint_debug_dev(sc->sc_dev,
674 "%s: failed burst rv %d\n", __func__, rv);
675#endif
676 return rv;
677 }
678 sc->sc_stat = tpm_status(sc);
679 if (!(sc->sc_stat & TPM_STS_DATA_EXPECT)) {
680#ifdef TPM_DEBUG
681 char sbuf[128];
682 snprintb(sbuf, sizeof(sbuf), TPM_STS_BITS, sc->sc_stat);
683 aprint_debug_dev(sc->sc_dev,
684 "%s: failed rv %d stat=%s\n", __func__, rv, sbuf);
685#endif
686 return EIO;
687 }
688 }
689
690 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_DATA, *p++);
691 cnt++;
692
693 if ((rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, sc))) {
694#ifdef TPM_DEBUG
695 aprint_debug_dev(sc->sc_dev, "%s: failed last byte rv %d\n",
696 __func__, rv);
697#endif
698 return rv;
699 }
700 if ((sc->sc_stat & TPM_STS_DATA_EXPECT) != 0) {
701#ifdef TPM_DEBUG
702 char sbuf[128];
703 snprintb(sbuf, sizeof(sbuf), TPM_STS_BITS, sc->sc_stat);
704 aprint_debug_dev(sc->sc_dev,
705 "%s: failed rv %d stat=%s\n", __func__, rv, sbuf);
706#endif
707 return EIO;
708 }
709
710#ifdef TPM_DEBUG
711 aprint_debug_dev(sc->sc_dev, "%s: wrote %zu byte\n", __func__, cnt);
712#endif
713
714 return 0;
715}
716
717/* Finish transaction. */
718int
719tpm_tis12_end(struct tpm_softc *sc, int flag, int err)
720{
721 int rv = 0;
722
723 if (flag == UIO_READ) {
724 if ((rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO,
725 sc->sc_read)))
726 return rv;
727
728 /* Still more data? */
729 sc->sc_stat = tpm_status(sc);
730 if (!err && ((sc->sc_stat & TPM_STS_DATA_AVAIL)
731 == TPM_STS_DATA_AVAIL)) {
732#ifdef TPM_DEBUG
733 char buf[128];
734 snprintb(buf, sizeof(buf), TPM_STS_BITS, sc->sc_stat);
735 aprint_debug_dev(sc->sc_dev,
736 "%s: read failed stat=%s\n", __func__, buf);
737#endif
738 rv = EIO;
739 }
740
741 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS,
742 TPM_STS_CMD_READY);
743
744 /* Release our (0th) locality. */
745 bus_space_write_1(sc->sc_bt, sc->sc_bh,TPM_ACCESS,
746 TPM_ACCESS_ACTIVE_LOCALITY);
747 } else {
748 /* Hungry for more? */
749 sc->sc_stat = tpm_status(sc);
750 if (!err && (sc->sc_stat & TPM_STS_DATA_EXPECT)) {
751#ifdef TPM_DEBUG
752 char buf[128];
753 snprintb(buf, sizeof(buf), TPM_STS_BITS, sc->sc_stat);
754 aprint_debug_dev(sc->sc_dev,
755 "%s: write failed stat=%s\n", __func__, buf);
756#endif
757 rv = EIO;
758 }
759
760 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS,
761 err ? TPM_STS_CMD_READY : TPM_STS_GO);
762 }
763
764 return rv;
765}
766
767int
768tpm_intr(void *v)
769{
770 struct tpm_softc *sc = v;
771 uint32_t r;
772#ifdef TPM_DEBUG
773 static int cnt = 0;
774#endif
775
776 r = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS);
777#ifdef TPM_DEBUG
778 if (r != 0) {
779 char buf[128];
780 snprintb(buf, sizeof(buf), TPM_INTERRUPT_ENABLE_BITS, r);
781 aprint_debug_dev(sc->sc_dev, "%s: int=%s (%d)\n", __func__,
782 buf, cnt);
783 } else
784 cnt++;
785#endif
786 if (!(r & (TPM_CMD_READY_INT | TPM_LOCALITY_CHANGE_INT |
787 TPM_STS_VALID_INT | TPM_DATA_AVAIL_INT)))
788#ifdef __FreeBSD__
789 return;
790#else
791 return 0;
792#endif
793 if (r & TPM_STS_VALID_INT)
794 wakeup(sc);
795
796 if (r & TPM_CMD_READY_INT)
797 wakeup(sc->sc_write);
798
799 if (r & TPM_DATA_AVAIL_INT)
800 wakeup(sc->sc_read);
801
802 if (r & TPM_LOCALITY_CHANGE_INT)
803 wakeup(sc->sc_init);
804
805 bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS, r);
806
807 return 1;
808}
809
810/* Read single byte using legacy interface. */
811static inline uint8_t
812tpm_legacy_in(bus_space_tag_t iot, bus_space_handle_t ioh, int reg)
813{
814 bus_space_write_1(iot, ioh, 0, reg);
815 return bus_space_read_1(iot, ioh, 1);
816}
817
818/* Probe for TPM using legacy interface. */
819int
820tpm_legacy_probe(bus_space_tag_t iot, bus_addr_t iobase)
821{
822 bus_space_handle_t ioh;
823 uint8_t r, v;
824 int i, rv = 0;
825 char id[8];
826
827 if (!tpm_enabled || iobase == -1)
828 return 0;
829
830 if (bus_space_map(iot, iobase, 2, 0, &ioh))
831 return 0;
832
833 v = bus_space_read_1(iot, ioh, 0);
834 if (v == 0xff) {
835 bus_space_unmap(iot, ioh, 2);
836 return 0;
837 }
838 r = bus_space_read_1(iot, ioh, 1);
839
840 for (i = sizeof(id); i--; )
841 id[i] = tpm_legacy_in(iot, ioh, TPM_ID + i);
842
843#ifdef TPM_DEBUG
844 printf("tpm_legacy_probe %.4s %d.%d.%d.%d\n",
845 &id[4], id[0], id[1], id[2], id[3]);
846#endif
847 /*
848 * The only chips using the legacy interface we are aware of are
849 * by Atmel. For other chips more signature would have to be added.
850 */
851 if (!bcmp(&id[4], "ATML", 4))
852 rv = 1;
853
854 if (!rv) {
855 bus_space_write_1(iot, ioh, r, 1);
856 bus_space_write_1(iot, ioh, v, 0);
857 }
858 bus_space_unmap(iot, ioh, 2);
859
860 return rv;
861}
862
863/* Setup TPM using legacy interface. */
864int
865tpm_legacy_init(struct tpm_softc *sc, int irq, const char *name)
866{
867 char id[8];
868 int i;
869
870 if ((i = bus_space_map(sc->sc_batm, tpm_enabled, 2, 0, &sc->sc_bahm))) {
871 aprint_debug_dev(sc->sc_dev, "cannot map tpm registers (%d)\n",
872 i);
873 tpm_enabled = 0;
874 return 1;
875 }
876
877 for (i = sizeof(id); i--; )
878 id[i] = tpm_legacy_in(sc->sc_bt, sc->sc_bh, TPM_ID + i);
879
880 aprint_debug_dev(sc->sc_dev, "%.4s %d.%d @0x%x\n", &id[4], id[0],
881 id[1], tpm_enabled);
882 tpm_enabled = 0;
883
884 return 0;
885}
886
887/* Start transaction. */
888int
889tpm_legacy_start(struct tpm_softc *sc, int flag)
890{
891 struct timeval tv;
892 uint8_t bits, r;
893 int to, rv;
894
895 bits = flag == UIO_READ ? TPM_LEGACY_DA : 0;
896 tv.tv_sec = TPM_LEGACY_TMO;
897 tv.tv_usec = 0;
898 to = tvtohz(&tv) / TPM_LEGACY_SLEEP;
899 while (((r = bus_space_read_1(sc->sc_batm, sc->sc_bahm, 1)) &
900 (TPM_LEGACY_BUSY|bits)) != bits && to--) {
901 rv = tsleep(sc, PRIBIO | PCATCH, "legacy_tpm_start",
902 TPM_LEGACY_SLEEP);
903 if (rv && rv != EWOULDBLOCK)
904 return rv;
905 }
906
907#if defined(TPM_DEBUG) && !defined(__FreeBSD__)
908 char buf[128];
909 snprintb(buf, sizeof(buf), TPM_LEGACY_BITS, r);
910 aprint_debug_dev(sc->sc_dev, "%s: bits %s\n", device_xname(sc->sc_dev),
911 buf);
912#endif
913 if ((r & (TPM_LEGACY_BUSY|bits)) != bits)
914 return EIO;
915
916 return 0;
917}
918
919int
920tpm_legacy_read(struct tpm_softc *sc, void *buf, size_t len, size_t *count,
921 int flags)
922{
923 uint8_t *p;
924 size_t cnt;
925 int to, rv;
926
927 cnt = rv = 0;
928 for (p = buf; !rv && len > 0; len--) {
929 for (to = 1000;
930 !(bus_space_read_1(sc->sc_batm, sc->sc_bahm, 1) &
931 TPM_LEGACY_DA); DELAY(1))
932 if (!to--)
933 return EIO;
934
935 DELAY(TPM_LEGACY_DELAY);
936 *p++ = bus_space_read_1(sc->sc_batm, sc->sc_bahm, 0);
937 cnt++;
938 }
939
940 *count = cnt;
941 return 0;
942}
943
944int
945tpm_legacy_write(struct tpm_softc *sc, const void *buf, size_t len)
946{
947 const uint8_t *p;
948 size_t n;
949
950 for (p = buf, n = len; n--; DELAY(TPM_LEGACY_DELAY)) {
951 if (!n && len != TPM_BUFSIZ) {
952 bus_space_write_1(sc->sc_batm, sc->sc_bahm, 1,
953 TPM_LEGACY_LAST);
954 DELAY(TPM_LEGACY_DELAY);
955 }
956 bus_space_write_1(sc->sc_batm, sc->sc_bahm, 0, *p++);
957 }
958
959 return 0;
960}
961
962/* Finish transaction. */
963int
964tpm_legacy_end(struct tpm_softc *sc, int flag, int rv)
965{
966 struct timeval tv;
967 uint8_t r;
968 int to;
969
970 if (rv || flag == UIO_READ)
971 bus_space_write_1(sc->sc_batm, sc->sc_bahm, 1, TPM_LEGACY_ABRT);
972 else {
973 tv.tv_sec = TPM_LEGACY_TMO;
974 tv.tv_usec = 0;
975 to = tvtohz(&tv) / TPM_LEGACY_SLEEP;
976 while(((r = bus_space_read_1(sc->sc_batm, sc->sc_bahm, 1)) &
977 TPM_LEGACY_BUSY) && to--) {
978 rv = tsleep(sc, PRIBIO | PCATCH, "legacy_tpm_end",
979 TPM_LEGACY_SLEEP);
980 if (rv && rv != EWOULDBLOCK)
981 return rv;
982 }
983
984#if defined(TPM_DEBUG) && !defined(__FreeBSD__)
985 char buf[128];
986 snprintb(buf, sizeof(buf), TPM_LEGACY_BITS, r);
987 aprint_debug_dev(sc->sc_dev, "%s: bits %s\n",
988 device_xname(sc->sc_dev), buf);
989#endif
990 if (r & TPM_LEGACY_BUSY)
991 return EIO;
992
993 if (r & TPM_LEGACY_RE)
994 return EIO; /* XXX Retry the loop? */
995 }
996
997 return rv;
998}
999
1000int
1001tpmopen(dev_t dev, int flag, int mode, struct lwp *l)
1002{
1003 struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev));
1004
1005 if (!sc)
1006 return ENXIO;
1007
1008 if (sc->sc_flags & TPM_OPEN)
1009 return EBUSY;
1010
1011 sc->sc_flags |= TPM_OPEN;
1012
1013 return 0;
1014}
1015
1016int
1017tpmclose(dev_t dev, int flag, int mode, struct lwp *l)
1018{
1019 struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev));
1020
1021 if (!sc)
1022 return ENXIO;
1023
1024 if (!(sc->sc_flags & TPM_OPEN))
1025 return EINVAL;
1026
1027 sc->sc_flags &= ~TPM_OPEN;
1028
1029 return 0;
1030}
1031
1032int
1033tpmread(dev_t dev, struct uio *uio, int flags)
1034{
1035 struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev));
1036 uint8_t buf[TPM_BUFSIZ], *p;
1037 size_t cnt, len, n;
1038 int rv, s;
1039
1040 if (!sc)
1041 return ENXIO;
1042
1043 s = spltty();
1044 if ((rv = (*sc->sc_start)(sc, UIO_READ)))
1045 goto out;
1046
1047#ifdef TPM_DEBUG
1048 aprint_debug_dev(sc->sc_dev, "%s: getting header\n", __func__);
1049#endif
1050 if ((rv = (*sc->sc_read)(sc, buf, TPM_HDRSIZE, &cnt, 0))) {
1051 (*sc->sc_end)(sc, UIO_READ, rv);
1052 goto out;
1053 }
1054
1055 len = (buf[2] << 24) | (buf[3] << 16) | (buf[4] << 8) | buf[5];
1056#ifdef TPM_DEBUG
1057 aprint_debug_dev(sc->sc_dev, "%s: len %zu, io count %zu\n", __func__,
1058 len, uio->uio_resid);
1059#endif
1060 if (len > uio->uio_resid) {
1061 rv = EIO;
1062 (*sc->sc_end)(sc, UIO_READ, rv);
1063#ifdef TPM_DEBUG
1064 aprint_debug_dev(sc->sc_dev,
1065 "%s: bad residual io count 0x%zx\n", __func__,
1066 uio->uio_resid);
1067#endif
1068 goto out;
1069 }
1070
1071 /* Copy out header. */
1072 if ((rv = uiomove(buf, cnt, uio))) {
1073#ifdef TPM_DEBUG
1074 aprint_debug_dev(sc->sc_dev,
1075 "%s: uiomove failed %d\n", __func__, rv);
1076#endif
1077 (*sc->sc_end)(sc, UIO_READ, rv);
1078 goto out;
1079 }
1080
1081 /* Get remaining part of the answer (if anything is left). */
1082 for (len -= cnt, p = buf, n = sizeof(buf); len > 0; p = buf, len -= n,
1083 n = sizeof(buf)) {
1084 n = MIN(n, len);
1085#ifdef TPM_DEBUG
1086 aprint_debug_dev(sc->sc_dev, "%s: n %zu len %zu\n", __func__,
1087 n, len);
1088#endif
1089 if ((rv = (*sc->sc_read)(sc, p, n, NULL, TPM_PARAM_SIZE))) {
1090 (*sc->sc_end)(sc, UIO_READ, rv);
1091 goto out;
1092 }
1093 p += n;
1094 if ((rv = uiomove(buf, p - buf, uio))) {
1095#ifdef TPM_DEBUG
1096 aprint_debug_dev(sc->sc_dev,
1097 "%s: uiomove failed %d\n", __func__, rv);
1098#endif
1099 (*sc->sc_end)(sc, UIO_READ, rv);
1100 goto out;
1101 }
1102 }
1103
1104 rv = (*sc->sc_end)(sc, UIO_READ, rv);
1105out:
1106 splx(s);
1107 return rv;
1108}
1109
1110int
1111tpmwrite(dev_t dev, struct uio *uio, int flags)
1112{
1113 struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev));
1114 uint8_t buf[TPM_BUFSIZ];
1115 int n, rv, s;
1116
1117 if (!sc)
1118 return ENXIO;
1119
1120 s = spltty();
1121
1122#ifdef TPM_DEBUG
1123 aprint_debug_dev(sc->sc_dev, "%s: io count %zu\n", __func__,
1124 uio->uio_resid);
1125#endif
1126
1127 n = MIN(sizeof(buf), uio->uio_resid);
1128 if ((rv = uiomove(buf, n, uio))) {
1129#ifdef TPM_DEBUG
1130 aprint_debug_dev(sc->sc_dev,
1131 "%s: uiomove failed %d\n", __func__, rv);
1132#endif
1133 splx(s);
1134 return rv;
1135 }
1136
1137 if ((rv = (*sc->sc_start)(sc, UIO_WRITE))) {
1138 splx(s);
1139 return rv;
1140 }
1141
1142 if ((rv = (*sc->sc_write)(sc, buf, n))) {
1143 splx(s);
1144 return rv;
1145 }
1146
1147 rv = (*sc->sc_end)(sc, UIO_WRITE, rv);
1148 splx(s);
1149 return rv;
1150}
1151
1152int
1153tpmioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
1154{
1155 return ENOTTY;
1156}
1157