2 * Copyright (c) 2008, 2009 Michael Shalayeff
3 * Copyright (c) 2009, 2010 Hans-Joerg Hoexer
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
15 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
16 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 * $FreeBSD: src/sys/dev/tpm/tpm.c,v 1.1 2010/08/12 00:16:18 takawata Exp $
21 /* #define TPM_DEBUG */
23 #include <sys/param.h>
24 #include <sys/systm.h>
25 #include <sys/kernel.h>
26 #include <sys/malloc.h>
29 #include <sys/module.h>
33 #include <sys/device.h>
34 #include <sys/thread2.h>
38 #include <machine/md_var.h>
40 #include <bus/isa/isareg.h>
41 #include <bus/isa/isavar.h>
43 #include <dev/crypto/tpm/tpmvar.h>
45 #define TPM_BUFSIZ 1024
47 #define TPM_HDRSIZE 10
49 #define TPM_PARAM_SIZE 0x0001
53 #define TPM_ACCESS 0x0000 /* acess register */
54 #define TPM_ACCESS_ESTABLISHMENT 0x01 /* establishment */
55 #define TPM_ACCESS_REQUEST_USE 0x02 /* request using locality */
56 #define TPM_ACCESS_REQUEST_PENDING 0x04 /* pending request */
57 #define TPM_ACCESS_SEIZE 0x08 /* request locality seize */
58 #define TPM_ACCESS_SEIZED 0x10 /* locality has been seized */
59 #define TPM_ACCESS_ACTIVE_LOCALITY 0x20 /* locality is active */
60 #define TPM_ACCESS_VALID 0x80 /* bits are valid */
61 #define TPM_ACCESS_BITS \
62 "\020\01EST\02REQ\03PEND\04SEIZE\05SEIZED\06ACT\010VALID"
64 #define TPM_INTERRUPT_ENABLE 0x0008
65 #define TPM_GLOBAL_INT_ENABLE 0x80000000 /* enable ints */
66 #define TPM_CMD_READY_INT 0x00000080 /* cmd ready enable */
67 #define TPM_INT_EDGE_FALLING 0x00000018
68 #define TPM_INT_EDGE_RISING 0x00000010
69 #define TPM_INT_LEVEL_LOW 0x00000008
70 #define TPM_INT_LEVEL_HIGH 0x00000000
71 #define TPM_LOCALITY_CHANGE_INT 0x00000004 /* locality change enable */
72 #define TPM_STS_VALID_INT 0x00000002 /* int on TPM_STS_VALID is set */
73 #define TPM_DATA_AVAIL_INT 0x00000001 /* int on TPM_STS_DATA_AVAIL is set */
74 #define TPM_INTERRUPT_ENABLE_BITS \
75 "\020\040ENA\010RDY\03LOCH\02STSV\01DRDY"
77 #define TPM_INT_VECTOR 0x000c /* 8 bit reg for 4 bit irq vector */
78 #define TPM_INT_STATUS 0x0010 /* bits are & 0x87 from TPM_INTERRUPT_ENABLE */
80 #define TPM_INTF_CAPABILITIES 0x0014 /* capability register */
81 #define TPM_INTF_BURST_COUNT_STATIC 0x0100 /* TPM_STS_BMASK static */
82 #define TPM_INTF_CMD_READY_INT 0x0080 /* int on ready supported */
83 #define TPM_INTF_INT_EDGE_FALLING 0x0040 /* falling edge ints supported */
84 #define TPM_INTF_INT_EDGE_RISING 0x0020 /* rising edge ints supported */
85 #define TPM_INTF_INT_LEVEL_LOW 0x0010 /* level-low ints supported */
86 #define TPM_INTF_INT_LEVEL_HIGH 0x0008 /* level-high ints supported */
87 #define TPM_INTF_LOCALITY_CHANGE_INT 0x0004 /* locality-change int (mb 1) */
88 #define TPM_INTF_STS_VALID_INT 0x0002 /* TPM_STS_VALID int supported */
89 #define TPM_INTF_DATA_AVAIL_INT 0x0001 /* TPM_STS_DATA_AVAIL int supported (mb 1) */
91 (TPM_INTF_DATA_AVAIL_INT|TPM_INTF_LOCALITY_CHANGE_INT|TPM_INTF_INT_LEVEL_LOW)
93 "\020\01IDRDY\02ISTSV\03ILOCH\04IHIGH\05ILOW\06IEDGE\07IFALL\010IRDY\011BCST"
95 #define TPM_STS 0x0018 /* status register */
96 #define TPM_STS_MASK 0x000000ff /* status bits */
97 #define TPM_STS_BMASK 0x00ffff00 /* ro io burst size */
98 #define TPM_STS_VALID 0x00000080 /* ro other bits are valid */
99 #define TPM_STS_CMD_READY 0x00000040 /* rw chip/signal ready */
100 #define TPM_STS_GO 0x00000020 /* wo start the command */
101 #define TPM_STS_DATA_AVAIL 0x00000010 /* ro data available */
102 #define TPM_STS_DATA_EXPECT 0x00000008 /* ro more data to be written */
103 #define TPM_STS_RESP_RETRY 0x00000002 /* wo resend the response */
104 #define TPM_STS_BITS "\020\010VALID\07RDY\06GO\05DRDY\04EXPECT\02RETRY"
106 #define TPM_DATA 0x0024
107 #define TPM_ID 0x0f00
108 #define TPM_REV 0x0f04
109 #define TPM_SIZE 0x5000 /* five pages of the above */
111 #define TPM_ACCESS_TMO 2000 /* 2sec */
112 #define TPM_READY_TMO 2000 /* 2sec */
113 #define TPM_READ_TMO 120000 /* 2 minutes */
114 #define TPM_BURST_TMO 2000 /* 2sec */
116 #define TPM_LEGACY_BUSY 0x01
117 #define TPM_LEGACY_ABRT 0x01
118 #define TPM_LEGACY_DA 0x02
119 #define TPM_LEGACY_RE 0x04
120 #define TPM_LEGACY_LAST 0x04
121 #define TPM_LEGACY_BITS "\020\01BUSY\2DA\3RE\4LAST"
122 #define TPM_LEGACY_TMO (2*60) /* sec */
123 #define TPM_LEGACY_SLEEP 5 /* ticks */
124 #define TPM_LEGACY_DELAY 100
126 /* Set when enabling legacy interface in host bridge. */
130 #define TPMSOFTC(dev) \
131 ((struct tpm_softc *)dev->si_drv1)
139 static struct dev_ops tpm_ops
= {
152 #define TPM_DEV_NOINTS 0x0001
154 { 0x000615d1, "IFX SLD 9630 TT 1.1", 0 },
155 { 0x000b15d1, "IFX SLB 9635 TT 1.2", 0 },
156 { 0x100214e4, "Broadcom BCM0102", TPM_DEV_NOINTS
},
157 { 0x00fe1050, "WEC WPCT200", 0 },
158 { 0x687119fa, "SNS SSX35", 0 },
159 { 0x2e4d5453, "STM ST19WP18", 0 },
160 { 0x32021114, "ATML 97SC3203", TPM_DEV_NOINTS
},
161 { 0x10408086, "INTEL INTC0102", 0 },
162 { 0, "", TPM_DEV_NOINTS
},
165 int tpm_tis12_irqinit(struct tpm_softc
*, int, int);
166 int tpm_tis12_init(struct tpm_softc
*, int, const char *);
167 int tpm_tis12_start(struct tpm_softc
*, int);
168 int tpm_tis12_read(struct tpm_softc
*, void *, int, size_t *, int);
169 int tpm_tis12_write(struct tpm_softc
*, void *, int);
170 int tpm_tis12_end(struct tpm_softc
*, int, int);
172 void tpm_intr(void *);
174 int tpm_waitfor_poll(struct tpm_softc
*, u_int8_t
, int, void *);
175 int tpm_waitfor_int(struct tpm_softc
*, u_int8_t
, int, void *, int);
176 int tpm_waitfor(struct tpm_softc
*, u_int8_t
, int, void *);
177 int tpm_request_locality(struct tpm_softc
*, int);
178 int tpm_getburst(struct tpm_softc
*);
179 u_int8_t
tpm_status(struct tpm_softc
*);
180 int tpm_tmotohz(int);
182 int tpm_legacy_probe(bus_space_tag_t
, bus_addr_t
);
183 int tpm_legacy_init(struct tpm_softc
*, int, const char *);
184 int tpm_legacy_start(struct tpm_softc
*, int);
185 int tpm_legacy_read(struct tpm_softc
*, void *, int, size_t *, int);
186 int tpm_legacy_write(struct tpm_softc
*, void *, int);
187 int tpm_legacy_end(struct tpm_softc
*, int, int);
190 * FreeBSD specific code for probing and attaching TPM to device tree.
194 tpm_identify(driver_t
*driver
, device_t parent
)
196 BUS_ADD_CHILD(parent
, ISA_ORDER_SPECULATIVE
, "tpm", 0);
202 tpm_attach(device_t dev
)
204 struct tpm_softc
*sc
= device_get_softc(dev
);
208 sc
->mem_res
= bus_alloc_resource_any(dev
, SYS_RES_MEMORY
, &sc
->mem_rid
,
210 if (sc
->mem_res
== NULL
)
213 sc
->sc_bt
= rman_get_bustag(sc
->mem_res
);
214 sc
->sc_bh
= rman_get_bushandle(sc
->mem_res
);
217 sc
->irq_res
= bus_alloc_resource_any(dev
, SYS_RES_IRQ
, &sc
->irq_rid
,
218 RF_ACTIVE
| RF_SHAREABLE
);
219 if (sc
->irq_res
!= NULL
)
220 irq
= rman_get_start(sc
->irq_res
);
224 /* In case PnP probe this may contain some initialization. */
225 tpm_tis12_probe(sc
->sc_bt
, sc
->sc_bh
);
227 if (tpm_legacy_probe(sc
->sc_bt
, sc
->sc_bh
)) {
228 sc
->sc_init
= tpm_legacy_init
;
229 sc
->sc_start
= tpm_legacy_start
;
230 sc
->sc_read
= tpm_legacy_read
;
231 sc
->sc_write
= tpm_legacy_write
;
232 sc
->sc_end
= tpm_legacy_end
;
234 sc
->sc_init
= tpm_tis12_init
;
235 sc
->sc_start
= tpm_tis12_start
;
236 sc
->sc_read
= tpm_tis12_read
;
237 sc
->sc_write
= tpm_tis12_write
;
238 sc
->sc_end
= tpm_tis12_end
;
241 kprintf("%s", device_get_name(dev
));
242 if ((sc
->sc_init
)(sc
, irq
, "tpm")) {
247 if (sc
->sc_init
== tpm_tis12_init
&& sc
->irq_res
!= NULL
&&
248 bus_setup_intr(dev
, sc
->irq_res
, 0,
249 tpm_intr
, sc
, &sc
->intr_cookie
, NULL
) != 0) {
251 kprintf(": cannot establish interrupt\n");
255 sc
->sc_cdev
= make_dev(&tpm_ops
, device_get_unit(dev
),
256 UID_ROOT
, GID_WHEEL
, 0600, "tpm");
257 sc
->sc_cdev
->si_drv1
= sc
;
263 tpm_detach(device_t dev
)
265 struct tpm_softc
* sc
= device_get_softc(dev
);
268 bus_teardown_intr(dev
, sc
->irq_res
, sc
->intr_cookie
);
272 bus_release_resource(dev
, SYS_RES_MEMORY
,
273 sc
->mem_rid
, sc
->mem_res
);
277 bus_release_resource(dev
, SYS_RES_IRQ
,
278 sc
->irq_rid
, sc
->irq_res
);
281 destroy_dev(sc
->sc_cdev
);
287 /* Probe TPM using TIS 1.2 interface. */
289 tpm_tis12_probe(bus_space_tag_t bt
, bus_space_handle_t bh
)
294 r
= bus_space_read_4(bt
, bh
, TPM_INTF_CAPABILITIES
);
299 kprintf("tpm: caps=%b\n", r
, TPM_CAPBITS
);
301 if ((r
& TPM_CAPSREQ
) != TPM_CAPSREQ
||
302 !(r
& (TPM_INTF_INT_EDGE_RISING
| TPM_INTF_INT_LEVEL_LOW
))) {
304 kprintf("tpm: caps too low (caps=%b)\n", r
, TPM_CAPBITS
);
309 save
= bus_space_read_1(bt
, bh
, TPM_ACCESS
);
310 bus_space_write_1(bt
, bh
, TPM_ACCESS
, TPM_ACCESS_REQUEST_USE
);
311 reg
= bus_space_read_1(bt
, bh
, TPM_ACCESS
);
312 if ((reg
& TPM_ACCESS_VALID
) && (reg
& TPM_ACCESS_ACTIVE_LOCALITY
) &&
313 bus_space_read_4(bt
, bh
, TPM_ID
) != 0xffffffff)
316 bus_space_write_1(bt
, bh
, TPM_ACCESS
, save
);
321 * Setup interrupt vector if one is provided and interrupts are know to
322 * work on that particular chip.
325 tpm_tis12_irqinit(struct tpm_softc
*sc
, int irq
, int idx
)
329 if ((irq
== IRQUNK
) || (tpm_devs
[idx
].flags
& TPM_DEV_NOINTS
)) {
330 sc
->sc_vector
= IRQUNK
;
334 /* Ack and disable all interrupts. */
335 bus_space_write_4(sc
->sc_bt
, sc
->sc_bh
, TPM_INTERRUPT_ENABLE
,
336 bus_space_read_4(sc
->sc_bt
, sc
->sc_bh
, TPM_INTERRUPT_ENABLE
) &
337 ~TPM_GLOBAL_INT_ENABLE
);
338 bus_space_write_4(sc
->sc_bt
, sc
->sc_bh
, TPM_INT_STATUS
,
339 bus_space_read_4(sc
->sc_bt
, sc
->sc_bh
, TPM_INT_STATUS
));
341 /* Program interrupt vector. */
342 bus_space_write_1(sc
->sc_bt
, sc
->sc_bh
, TPM_INT_VECTOR
, irq
);
345 /* Program interrupt type. */
346 if (sc
->sc_capabilities
& TPM_INTF_INT_EDGE_RISING
)
347 r
= TPM_INT_EDGE_RISING
;
348 else if (sc
->sc_capabilities
& TPM_INTF_INT_LEVEL_HIGH
)
349 r
= TPM_INT_LEVEL_HIGH
;
351 r
= TPM_INT_LEVEL_LOW
;
352 bus_space_write_4(sc
->sc_bt
, sc
->sc_bh
, TPM_INTERRUPT_ENABLE
, r
);
357 /* Setup TPM using TIS 1.2 interface. */
359 tpm_tis12_init(struct tpm_softc
*sc
, int irq
, const char *name
)
364 r
= bus_space_read_4(sc
->sc_bt
, sc
->sc_bh
, TPM_INTF_CAPABILITIES
);
366 kprintf(" caps=%b ", r
, TPM_CAPBITS
);
368 if ((r
& TPM_CAPSREQ
) != TPM_CAPSREQ
||
369 !(r
& (TPM_INTF_INT_EDGE_RISING
| TPM_INTF_INT_LEVEL_LOW
))) {
370 kprintf(": capabilities too low (caps=%b)\n", r
, TPM_CAPBITS
);
373 sc
->sc_capabilities
= r
;
375 sc
->sc_devid
= bus_space_read_4(sc
->sc_bt
, sc
->sc_bh
, TPM_ID
);
376 sc
->sc_rev
= bus_space_read_1(sc
->sc_bt
, sc
->sc_bh
, TPM_REV
);
378 for (i
= 0; tpm_devs
[i
].devid
; i
++)
379 if (tpm_devs
[i
].devid
== sc
->sc_devid
)
382 if (tpm_devs
[i
].devid
)
383 kprintf(": %s rev 0x%x\n", tpm_devs
[i
].name
, sc
->sc_rev
);
385 kprintf(": device 0x%08x rev 0x%x\n", sc
->sc_devid
, sc
->sc_rev
);
387 if (tpm_tis12_irqinit(sc
, irq
, i
))
390 if (tpm_request_locality(sc
, 0))
393 /* Abort whatever it thought it was doing. */
394 bus_space_write_1(sc
->sc_bt
, sc
->sc_bh
, TPM_STS
, TPM_STS_CMD_READY
);
400 tpm_request_locality(struct tpm_softc
*sc
, int l
)
408 if ((bus_space_read_1(sc
->sc_bt
, sc
->sc_bh
, TPM_ACCESS
) &
409 (TPM_ACCESS_VALID
| TPM_ACCESS_ACTIVE_LOCALITY
)) ==
410 (TPM_ACCESS_VALID
| TPM_ACCESS_ACTIVE_LOCALITY
))
413 bus_space_write_1(sc
->sc_bt
, sc
->sc_bh
, TPM_ACCESS
,
414 TPM_ACCESS_REQUEST_USE
);
416 to
= tpm_tmotohz(TPM_ACCESS_TMO
);
418 while ((r
= bus_space_read_1(sc
->sc_bt
, sc
->sc_bh
, TPM_ACCESS
) &
419 (TPM_ACCESS_VALID
| TPM_ACCESS_ACTIVE_LOCALITY
)) !=
420 (TPM_ACCESS_VALID
| TPM_ACCESS_ACTIVE_LOCALITY
) && to
--) {
421 rv
= tsleep(sc
->sc_init
, PCATCH
, "tpm_locality", 1);
422 if (rv
&& rv
!= EWOULDBLOCK
) {
424 kprintf("%s: interrupted %d\n", __func__
, rv
);
430 if ((r
& (TPM_ACCESS_VALID
| TPM_ACCESS_ACTIVE_LOCALITY
)) !=
431 (TPM_ACCESS_VALID
| TPM_ACCESS_ACTIVE_LOCALITY
)) {
433 kprintf("%s: access %b\n", __func__
, r
, TPM_ACCESS_BITS
);
442 tpm_getburst(struct tpm_softc
*sc
)
446 to
= tpm_tmotohz(TPM_BURST_TMO
);
449 while (burst
== 0 && to
--) {
451 * Burst count has to be read from bits 8 to 23 without
452 * touching any other bits, eg. the actual status bits 0
455 burst
= bus_space_read_1(sc
->sc_bt
, sc
->sc_bh
, TPM_STS
+ 1);
456 burst
|= bus_space_read_1(sc
->sc_bt
, sc
->sc_bh
, TPM_STS
+ 2)
459 kprintf("%s: read %d\n", __func__
, burst
);
464 rv
= tsleep(sc
, PCATCH
, "tpm_getburst", 1);
465 if (rv
&& rv
!= EWOULDBLOCK
) {
474 tpm_status(struct tpm_softc
*sc
)
478 status
= bus_space_read_1(sc
->sc_bt
, sc
->sc_bh
, TPM_STS
) &
489 tv
.tv_sec
= tmo
/ 1000;
490 tv
.tv_usec
= 1000 * (tmo
% 1000);
492 return tvtohz_high(&tv
);
495 /* Save TPM state on suspend. */
497 tpm_suspend(device_t dev
)
499 struct tpm_softc
*sc
= device_get_softc(dev
);
501 u_int8_t command
[] = {
502 0, 193, /* TPM_TAG_RQU_COMMAND */
503 0, 0, 0, 10, /* Length in bytes */
504 0, 0, 0, 156 /* TPM_ORD_SaveStates */
508 * Power down: We have to issue the SaveStates command.
510 sc
->sc_write(sc
, &command
, sizeof(command
));
511 sc
->sc_read(sc
, &command
, sizeof(command
), NULL
, TPM_HDRSIZE
);
513 kprintf("%s: power down: %d -> %d\n", __func__
, sc
->sc_suspend
, why
);
515 sc
->sc_suspend
= why
;
521 * Handle resume event. Actually nothing to do as the BIOS is supposed
522 * to restore the previously saved state.
525 tpm_resume(device_t dev
)
527 struct tpm_softc
*sc
= device_get_softc(dev
);
531 kprintf("%s: resume: %d -> %d\n", __func__
, sc
->sc_suspend
, why
);
533 sc
->sc_suspend
= why
;
538 /* Wait for given status bits using polling. */
540 tpm_waitfor_poll(struct tpm_softc
*sc
, u_int8_t mask
, int tmo
, void *c
)
545 * Poll until either the requested condition or a time out is
548 while (((sc
->sc_stat
= tpm_status(sc
)) & mask
) != mask
&& tmo
--) {
549 rv
= tsleep(c
, PCATCH
, "tpm_poll", 1);
550 if (rv
&& rv
!= EWOULDBLOCK
) {
552 kprintf("%s: interrupted %d\n", __func__
, rv
);
561 /* Wait for given status bits using interrupts. */
563 tpm_waitfor_int(struct tpm_softc
*sc
, u_int8_t mask
, int tmo
, void *c
,
568 /* Poll and return when condition is already met. */
569 sc
->sc_stat
= tpm_status(sc
);
570 if ((sc
->sc_stat
& mask
) == mask
)
574 * Enable interrupt on tpm chip. Note that interrupts on our
575 * level (SPL_TTY) are disabled (see tpm{read,write} et al) and
576 * will not be delivered to the cpu until we call tsleep(9) below.
578 bus_space_write_4(sc
->sc_bt
, sc
->sc_bh
, TPM_INTERRUPT_ENABLE
,
579 bus_space_read_4(sc
->sc_bt
, sc
->sc_bh
, TPM_INTERRUPT_ENABLE
) |
581 bus_space_write_4(sc
->sc_bt
, sc
->sc_bh
, TPM_INTERRUPT_ENABLE
,
582 bus_space_read_4(sc
->sc_bt
, sc
->sc_bh
, TPM_INTERRUPT_ENABLE
) |
583 TPM_GLOBAL_INT_ENABLE
);
586 * Poll once more to remedy the race between previous polling
587 * and enabling interrupts on the tpm chip.
589 sc
->sc_stat
= tpm_status(sc
);
590 if ((sc
->sc_stat
& mask
) == mask
) {
595 to
= tpm_tmotohz(tmo
);
597 kprintf("%s: sleeping for %d ticks on %p\n", __func__
, to
, c
);
600 * tsleep(9) enables interrupts on the cpu and returns after
601 * wake up with interrupts disabled again. Note that interrupts
602 * generated by the tpm chip while being at SPL_TTY are not lost
603 * but held and delivered as soon as the cpu goes below SPL_TTY.
605 rv
= tsleep(c
, PCATCH
, "tpm_intr", to
);
607 sc
->sc_stat
= tpm_status(sc
);
609 kprintf("%s: woke up with rv %d stat %b\n", __func__
, rv
,
610 sc
->sc_stat
, TPM_STS_BITS
);
612 if ((sc
->sc_stat
& mask
) == mask
)
615 /* Disable interrupts on tpm chip again. */
616 out
: bus_space_write_4(sc
->sc_bt
, sc
->sc_bh
, TPM_INTERRUPT_ENABLE
,
617 bus_space_read_4(sc
->sc_bt
, sc
->sc_bh
, TPM_INTERRUPT_ENABLE
) &
618 ~TPM_GLOBAL_INT_ENABLE
);
619 bus_space_write_4(sc
->sc_bt
, sc
->sc_bh
, TPM_INTERRUPT_ENABLE
,
620 bus_space_read_4(sc
->sc_bt
, sc
->sc_bh
, TPM_INTERRUPT_ENABLE
) &
627 * Wait on given status bits, uses interrupts where possible, otherwise polls.
630 tpm_waitfor(struct tpm_softc
*sc
, u_int8_t b0
, int tmo
, void *c
)
636 kprintf("%s: b0 %b\n", __func__
, b0
, TPM_STS_BITS
);
640 * If possible, use interrupts, otherwise poll.
642 * We use interrupts for TPM_STS_VALID and TPM_STS_DATA_AVAIL (if
643 * the tpm chips supports them) as waiting for those can take
644 * really long. The other TPM_STS* are not needed very often
645 * so we do not support them.
647 if (sc
->sc_vector
!= IRQUNK
) {
651 * Wait for data ready. This interrupt only occures
652 * when both TPM_STS_VALID and TPM_STS_DATA_AVAIL are asserted.
653 * Thus we don't have to bother with TPM_STS_VALID
654 * separately and can just return.
656 * This only holds for interrupts! When using polling
657 * both flags have to be waited for, see below.
659 if ((b
& TPM_STS_DATA_AVAIL
) && (sc
->sc_capabilities
&
660 TPM_INTF_DATA_AVAIL_INT
))
661 return tpm_waitfor_int(sc
, b
, tmo
, c
,
664 /* Wait for status valid bit. */
665 if ((b
& TPM_STS_VALID
) && (sc
->sc_capabilities
&
666 TPM_INTF_STS_VALID_INT
)) {
667 rv
= tpm_waitfor_int(sc
, b
, tmo
, c
, TPM_STS_VALID_INT
);
671 b
= b0
& ~TPM_STS_VALID
;
675 * When all flags are taken care of, return. Otherwise
676 * use polling for eg. TPM_STS_CMD_READY.
685 * If requested wait for TPM_STS_VALID before dealing with
686 * any other flag. Eg. when both TPM_STS_DATA_AVAIL and TPM_STS_VALID
687 * are requested, wait for the latter first.
690 if (b0
& TPM_STS_VALID
)
693 to
= tpm_tmotohz(tmo
);
695 if ((rv
= tpm_waitfor_poll(sc
, b
, to
, c
)) != 0)
698 if ((b
& sc
->sc_stat
) == TPM_STS_VALID
) {
699 /* Now wait for other flags. */
700 b
= b0
& ~TPM_STS_VALID
;
705 if ((sc
->sc_stat
& b
) != b
) {
707 kprintf("%s: timeout: stat=%b b=%b\n", __func__
,
708 sc
->sc_stat
, TPM_STS_BITS
, b
, TPM_STS_BITS
);
710 if (re
-- && (b0
& TPM_STS_VALID
)) {
711 bus_space_write_1(sc
->sc_bt
, sc
->sc_bh
, TPM_STS
,
721 /* Start transaction. */
723 tpm_tis12_start(struct tpm_softc
*sc
, int flag
)
727 if (flag
== UIO_READ
) {
728 rv
= tpm_waitfor(sc
, TPM_STS_DATA_AVAIL
| TPM_STS_VALID
,
729 TPM_READ_TMO
, sc
->sc_read
);
733 /* Own our (0th) locality. */
734 if ((rv
= tpm_request_locality(sc
, 0)) != 0)
737 sc
->sc_stat
= tpm_status(sc
);
738 if (sc
->sc_stat
& TPM_STS_CMD_READY
) {
740 kprintf("%s: UIO_WRITE status %b\n", __func__
, sc
->sc_stat
,
747 kprintf("%s: UIO_WRITE readying chip\n", __func__
);
750 /* Abort previous and restart. */
751 bus_space_write_1(sc
->sc_bt
, sc
->sc_bh
, TPM_STS
, TPM_STS_CMD_READY
);
752 if ((rv
= tpm_waitfor(sc
, TPM_STS_CMD_READY
, TPM_READY_TMO
,
755 kprintf("%s: UIO_WRITE readying failed %d\n", __func__
, rv
);
761 kprintf("%s: UIO_WRITE readying done\n", __func__
);
768 tpm_tis12_read(struct tpm_softc
*sc
, void *buf
, int len
, size_t *count
,
776 kprintf("%s: len %d\n", __func__
, len
);
780 if ((rv
= tpm_waitfor(sc
, TPM_STS_DATA_AVAIL
| TPM_STS_VALID
,
781 TPM_READ_TMO
, sc
->sc_read
)))
784 bcnt
= tpm_getburst(sc
);
787 kprintf("%s: fetching %d, burst is %d\n", __func__
, n
, bcnt
);
790 *p
++ = bus_space_read_1(sc
->sc_bt
, sc
->sc_bh
, TPM_DATA
);
794 if ((flags
& TPM_PARAM_SIZE
) == 0 && cnt
>= 6)
798 kprintf("%s: read %zd bytes, len %d\n", __func__
, cnt
, len
);
808 tpm_tis12_write(struct tpm_softc
*sc
, void *buf
, int len
)
815 kprintf("%s: sc %p buf %p len %d\n", __func__
, sc
, buf
, len
);
818 if ((rv
= tpm_request_locality(sc
, 0)) != 0)
822 while (cnt
< len
- 1) {
823 for (r
= tpm_getburst(sc
); r
> 0 && cnt
< len
- 1; r
--) {
824 bus_space_write_1(sc
->sc_bt
, sc
->sc_bh
, TPM_DATA
, *p
++);
827 if ((rv
= tpm_waitfor(sc
, TPM_STS_VALID
, TPM_READ_TMO
, sc
))) {
829 kprintf("%s: failed burst rv %d\n", __func__
, rv
);
833 sc
->sc_stat
= tpm_status(sc
);
834 if (!(sc
->sc_stat
& TPM_STS_DATA_EXPECT
)) {
836 kprintf("%s: failed rv %d stat=%b\n", __func__
, rv
,
837 sc
->sc_stat
, TPM_STS_BITS
);
843 bus_space_write_1(sc
->sc_bt
, sc
->sc_bh
, TPM_DATA
, *p
++);
846 if ((rv
= tpm_waitfor(sc
, TPM_STS_VALID
, TPM_READ_TMO
, sc
))) {
848 kprintf("%s: failed last byte rv %d\n", __func__
, rv
);
852 if ((sc
->sc_stat
& TPM_STS_DATA_EXPECT
) != 0) {
854 kprintf("%s: failed rv %d stat=%b\n", __func__
, rv
,
855 sc
->sc_stat
, TPM_STS_BITS
);
861 kprintf("%s: wrote %zd byte\n", __func__
, cnt
);
867 /* Finish transaction. */
869 tpm_tis12_end(struct tpm_softc
*sc
, int flag
, int err
)
873 if (flag
== UIO_READ
) {
874 if ((rv
= tpm_waitfor(sc
, TPM_STS_VALID
, TPM_READ_TMO
,
878 /* Still more data? */
879 sc
->sc_stat
= tpm_status(sc
);
880 if (!err
&& ((sc
->sc_stat
& TPM_STS_DATA_AVAIL
) == TPM_STS_DATA_AVAIL
)) {
882 kprintf("%s: read failed stat=%b\n", __func__
,
883 sc
->sc_stat
, TPM_STS_BITS
);
888 bus_space_write_1(sc
->sc_bt
, sc
->sc_bh
, TPM_STS
,
891 /* Release our (0th) locality. */
892 bus_space_write_1(sc
->sc_bt
, sc
->sc_bh
,TPM_ACCESS
,
893 TPM_ACCESS_ACTIVE_LOCALITY
);
895 /* Hungry for more? */
896 sc
->sc_stat
= tpm_status(sc
);
897 if (!err
&& (sc
->sc_stat
& TPM_STS_DATA_EXPECT
)) {
899 kprintf("%s: write failed stat=%b\n", __func__
,
900 sc
->sc_stat
, TPM_STS_BITS
);
905 bus_space_write_1(sc
->sc_bt
, sc
->sc_bh
, TPM_STS
,
906 err
? TPM_STS_CMD_READY
: TPM_STS_GO
);
915 struct tpm_softc
*sc
= v
;
921 r
= bus_space_read_4(sc
->sc_bt
, sc
->sc_bh
, TPM_INT_STATUS
);
924 kprintf("%s: int=%b (%d)\n", __func__
, r
,
925 TPM_INTERRUPT_ENABLE_BITS
, cnt
);
929 if (!(r
& (TPM_CMD_READY_INT
| TPM_LOCALITY_CHANGE_INT
|
930 TPM_STS_VALID_INT
| TPM_DATA_AVAIL_INT
)))
933 if (r
& TPM_STS_VALID_INT
)
936 if (r
& TPM_CMD_READY_INT
)
937 wakeup(sc
->sc_write
);
939 if (r
& TPM_DATA_AVAIL_INT
)
942 if (r
& TPM_LOCALITY_CHANGE_INT
)
945 bus_space_write_4(sc
->sc_bt
, sc
->sc_bh
, TPM_INT_STATUS
, r
);
950 /* Read single byte using legacy interface. */
951 static inline u_int8_t
952 tpm_legacy_in(bus_space_tag_t iot
, bus_space_handle_t ioh
, int reg
)
954 bus_space_write_1(iot
, ioh
, 0, reg
);
955 return bus_space_read_1(iot
, ioh
, 1);
958 /* Write single byte using legacy interface. */
960 tpm_legacy_out(bus_space_tag_t iot
, bus_space_handle_t ioh
, int reg
, u_int8_t v
)
962 bus_space_write_1(iot
, ioh
, 0, reg
);
963 bus_space_write_1(iot
, ioh
, 1, v
);
966 /* Probe for TPM using legacy interface. */
968 tpm_legacy_probe(bus_space_tag_t iot
, bus_addr_t iobase
)
970 bus_space_handle_t ioh
;
975 if (!tpm_enabled
|| iobase
== -1)
978 #if 0 /* XXX swildner*/
979 if (bus_space_map(iot
, iobase
, 2, 0, &ioh
))
985 v
= bus_space_read_1(iot
, ioh
, 0);
987 bus_space_unmap(iot
, ioh
, 2);
990 r
= bus_space_read_1(iot
, ioh
, 1);
992 for (i
= sizeof(id
); i
--; )
993 id
[i
] = tpm_legacy_in(iot
, ioh
, TPM_ID
+ i
);
996 kprintf("%s: %.4s %d.%d.%d.%d\n", __func__
,
997 &id
[4], id
[0], id
[1], id
[2], id
[3]);
1000 * The only chips using the legacy interface we are aware of are
1001 * by Atmel. For other chips more signature would have to be added.
1003 if (!bcmp(&id
[4], "ATML", 4))
1007 bus_space_write_1(iot
, ioh
, r
, 1);
1008 bus_space_write_1(iot
, ioh
, v
, 0);
1010 bus_space_unmap(iot
, ioh
, 2);
1015 /* Setup TPM using legacy interface. */
1017 tpm_legacy_init(struct tpm_softc
*sc
, int irq
, const char *name
)
1023 #if 0 /* XXX swildner*/
1024 if ((i
= bus_space_map(sc
->sc_batm
, tpm_enabled
, 2, 0, &sc
->sc_bahm
))) {
1025 kprintf(": cannot map tpm registers (%d)\n", i
);
1030 sc
->sc_bahm
= tpm_enabled
;
1033 for (i
= sizeof(id
); i
--; )
1034 id
[i
] = tpm_legacy_in(sc
->sc_bt
, sc
->sc_bh
, TPM_ID
+ i
);
1036 kprintf(": %.4s %d.%d @0x%x\n", &id
[4], id
[0], id
[1], tpm_enabled
);
1037 iol
= tpm_enabled
& 0xff;
1038 ioh
= tpm_enabled
>> 16;
1044 /* Start transaction. */
1046 tpm_legacy_start(struct tpm_softc
*sc
, int flag
)
1052 bits
= flag
== UIO_READ
? TPM_LEGACY_DA
: 0;
1053 tv
.tv_sec
= TPM_LEGACY_TMO
;
1055 to
= tvtohz_high(&tv
) / TPM_LEGACY_SLEEP
;
1056 while (((r
= bus_space_read_1(sc
->sc_batm
, sc
->sc_bahm
, 1)) &
1057 (TPM_LEGACY_BUSY
|bits
)) != bits
&& to
--) {
1058 rv
= tsleep(sc
, PCATCH
, "legacy_tpm_start",
1060 if (rv
&& rv
!= EWOULDBLOCK
)
1064 if ((r
& (TPM_LEGACY_BUSY
|bits
)) != bits
)
1071 tpm_legacy_read(struct tpm_softc
*sc
, void *buf
, int len
, size_t *count
,
1079 for (p
= buf
; !rv
&& len
> 0; len
--) {
1081 !(bus_space_read_1(sc
->sc_batm
, sc
->sc_bahm
, 1) &
1082 TPM_LEGACY_DA
); DELAY(1))
1086 DELAY(TPM_LEGACY_DELAY
);
1087 *p
++ = bus_space_read_1(sc
->sc_batm
, sc
->sc_bahm
, 0);
1096 tpm_legacy_write(struct tpm_softc
*sc
, void *buf
, int len
)
1101 for (p
= buf
, n
= len
; n
--; DELAY(TPM_LEGACY_DELAY
)) {
1102 if (!n
&& len
!= TPM_BUFSIZ
) {
1103 bus_space_write_1(sc
->sc_batm
, sc
->sc_bahm
, 1,
1105 DELAY(TPM_LEGACY_DELAY
);
1107 bus_space_write_1(sc
->sc_batm
, sc
->sc_bahm
, 0, *p
++);
1113 /* Finish transaction. */
1115 tpm_legacy_end(struct tpm_softc
*sc
, int flag
, int rv
)
1121 if (rv
|| flag
== UIO_READ
)
1122 bus_space_write_1(sc
->sc_batm
, sc
->sc_bahm
, 1, TPM_LEGACY_ABRT
);
1124 tv
.tv_sec
= TPM_LEGACY_TMO
;
1126 to
= tvtohz_high(&tv
) / TPM_LEGACY_SLEEP
;
1127 while(((r
= bus_space_read_1(sc
->sc_batm
, sc
->sc_bahm
, 1)) &
1128 TPM_LEGACY_BUSY
) && to
--) {
1129 rv
= tsleep(sc
, PCATCH
, "legacy_tpm_end",
1131 if (rv
&& rv
!= EWOULDBLOCK
)
1135 if (r
& TPM_LEGACY_BUSY
)
1138 if (r
& TPM_LEGACY_RE
)
1139 return EIO
; /* XXX Retry the loop? */
1146 tpmopen(struct dev_open_args
*ap
)
1148 cdev_t dev
= ap
->a_head
.a_dev
;
1149 struct tpm_softc
*sc
= TPMSOFTC(dev
);
1154 if (sc
->sc_flags
& TPM_OPEN
)
1157 sc
->sc_flags
|= TPM_OPEN
;
1163 tpmclose(struct dev_close_args
*ap
)
1165 cdev_t dev
= ap
->a_head
.a_dev
;
1166 struct tpm_softc
*sc
= TPMSOFTC(dev
);
1171 if (!(sc
->sc_flags
& TPM_OPEN
))
1174 sc
->sc_flags
&= ~TPM_OPEN
;
1180 tpmread(struct dev_read_args
*ap
)
1182 cdev_t dev
= ap
->a_head
.a_dev
;
1183 struct uio
*uio
= ap
->a_uio
;
1184 struct tpm_softc
*sc
= TPMSOFTC(dev
);
1185 u_int8_t buf
[TPM_BUFSIZ
], *p
;
1193 if ((rv
= (sc
->sc_start
)(sc
, UIO_READ
))) {
1199 kprintf("%s: getting header\n", __func__
);
1201 if ((rv
= (sc
->sc_read
)(sc
, buf
, TPM_HDRSIZE
, &cnt
, 0))) {
1202 (sc
->sc_end
)(sc
, UIO_READ
, rv
);
1207 len
= (buf
[2] << 24) | (buf
[3] << 16) | (buf
[4] << 8) | buf
[5];
1209 kprintf("%s: len %d, io count %zd\n", __func__
, len
, uio
->uio_resid
);
1211 if (len
> uio
->uio_resid
) {
1213 (sc
->sc_end
)(sc
, UIO_READ
, rv
);
1215 kprintf("%s: bad residual io count 0x%zx\n", __func__
,
1222 /* Copy out header. */
1223 if ((rv
= uiomove((caddr_t
)buf
, cnt
, uio
))) {
1224 (sc
->sc_end
)(sc
, UIO_READ
, rv
);
1229 /* Get remaining part of the answer (if anything is left). */
1230 for (len
-= cnt
, p
= buf
, n
= sizeof(buf
); len
> 0; p
= buf
, len
-= n
,
1234 kprintf("%s: n %d len %d\n", __func__
, n
, len
);
1236 if ((rv
= (sc
->sc_read
)(sc
, p
, n
, NULL
, TPM_PARAM_SIZE
))) {
1237 (sc
->sc_end
)(sc
, UIO_READ
, rv
);
1242 if ((rv
= uiomove((caddr_t
)buf
, p
- buf
, uio
))) {
1243 (sc
->sc_end
)(sc
, UIO_READ
, rv
);
1249 rv
= (sc
->sc_end
)(sc
, UIO_READ
, rv
);
1255 tpmwrite(struct dev_write_args
*ap
)
1257 cdev_t dev
= ap
->a_head
.a_dev
;
1258 struct uio
*uio
= ap
->a_uio
;
1259 struct tpm_softc
*sc
= TPMSOFTC(dev
);
1260 u_int8_t buf
[TPM_BUFSIZ
];
1269 kprintf("%s: io count %zd\n", __func__
, uio
->uio_resid
);
1272 n
= MIN(sizeof(buf
), uio
->uio_resid
);
1273 if ((rv
= uiomove((caddr_t
)buf
, n
, uio
))) {
1278 if ((rv
= (sc
->sc_start
)(sc
, UIO_WRITE
))) {
1283 if ((rv
= (sc
->sc_write(sc
, buf
, n
)))) {
1288 rv
= (sc
->sc_end
)(sc
, UIO_WRITE
, rv
);
1294 tpmioctl(struct dev_ioctl_args
*ap
)