Home | History | Annotate | Line # | Download | only in ic
tpm.c revision 1.13
      1 /*	$NetBSD: tpm.c,v 1.13 2019/06/22 12:57:41 maxv Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2019 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Maxime Villard.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 /*
     33  * Copyright (c) 2008, 2009 Michael Shalayeff
     34  * Copyright (c) 2009, 2010 Hans-Joerg Hoexer
     35  * All rights reserved.
     36  *
     37  * Permission to use, copy, modify, and distribute this software for any
     38  * purpose with or without fee is hereby granted, provided that the above
     39  * copyright notice and this permission notice appear in all copies.
     40  *
     41  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     42  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     43  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     44  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     45  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
     46  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
     47  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     48  */
     49 
     50 #include <sys/cdefs.h>
     51 __KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.13 2019/06/22 12:57:41 maxv Exp $");
     52 
     53 #include <sys/param.h>
     54 #include <sys/systm.h>
     55 #include <sys/kernel.h>
     56 #include <sys/malloc.h>
     57 #include <sys/proc.h>
     58 #include <sys/device.h>
     59 #include <sys/conf.h>
     60 #include <sys/bus.h>
     61 #include <sys/pmf.h>
     62 
     63 #include <dev/ic/tpmreg.h>
     64 #include <dev/ic/tpmvar.h>
     65 
     66 #include "ioconf.h"
     67 
     68 #define TPM_BUFSIZ	1024
     69 #define TPM_HDRSIZE	10
     70 #define TPM_PARAM_SIZE	0x0001	/* that's a flag */
     71 
     72 /* Timeouts. */
     73 #define TPM_ACCESS_TMO	2000	/* 2sec */
     74 #define TPM_READY_TMO	2000	/* 2sec */
     75 #define TPM_READ_TMO	2000	/* 2sec */
     76 #define TPM_BURST_TMO	2000	/* 2sec */
     77 
     78 #define TPM_CAPS_REQUIRED \
     79 	(TPM_INTF_DATA_AVAIL_INT|TPM_INTF_LOCALITY_CHANGE_INT| \
     80 	 TPM_INTF_INT_LEVEL_LOW)
     81 
     82 static const struct {
     83 	uint32_t devid;
     84 	const char *name;
     85 	int flags;
     86 #define TPM_DEV_NOINTS	0x0001
     87 } tpm_devs[] = {
     88 	{ 0x000615d1, "IFX SLD 9630 TT 1.1", 0 },
     89 	{ 0x000b15d1, "IFX SLB 9635 TT 1.2", 0 },
     90 	{ 0x100214e4, "Broadcom BCM0102", TPM_DEV_NOINTS },
     91 	{ 0x00fe1050, "WEC WPCT200", 0 },
     92 	{ 0x687119fa, "SNS SSX35", 0 },
     93 	{ 0x2e4d5453, "STM ST19WP18", 0 },
     94 	{ 0x32021114, "ATML 97SC3203", TPM_DEV_NOINTS },
     95 	{ 0x10408086, "INTEL INTC0102", 0 },
     96 	{ 0, "", TPM_DEV_NOINTS },
     97 };
     98 
     99 static inline int
    100 tpm_tmotohz(int tmo)
    101 {
    102 	struct timeval tv;
    103 
    104 	tv.tv_sec = tmo / 1000;
    105 	tv.tv_usec = 1000 * (tmo % 1000);
    106 
    107 	return tvtohz(&tv);
    108 }
    109 
    110 static int
    111 tpm_request_locality(struct tpm_softc *sc, int l)
    112 {
    113 	uint32_t r;
    114 	int to, rv;
    115 
    116 	if (l != 0)
    117 		return EINVAL;
    118 
    119 	if ((bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS) &
    120 	    (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) ==
    121 	    (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY))
    122 		return 0;
    123 
    124 	bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS,
    125 	    TPM_ACCESS_REQUEST_USE);
    126 
    127 	to = tpm_tmotohz(TPM_ACCESS_TMO);
    128 
    129 	while ((r = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS) &
    130 	    (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
    131 	    (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY) && to--) {
    132 		rv = tsleep(sc->sc_init, PRIBIO | PCATCH, "tpm_locality", 1);
    133 		if (rv && rv != EWOULDBLOCK) {
    134 			return rv;
    135 		}
    136 	}
    137 
    138 	if ((r & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
    139 	    (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) {
    140 		return EBUSY;
    141 	}
    142 
    143 	return 0;
    144 }
    145 
    146 static int
    147 tpm_getburst(struct tpm_softc *sc)
    148 {
    149 	int burst, to, rv;
    150 
    151 	to = tpm_tmotohz(TPM_BURST_TMO);
    152 
    153 	while (to--) {
    154 		/*
    155 		 * Burst count is in bits 23:8, so read the two higher bytes.
    156 		 */
    157 		burst = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_STS + 1);
    158 		burst |= bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_STS + 2)
    159 		    << 8;
    160 
    161 		if (burst)
    162 			return burst;
    163 
    164 		rv = tsleep(sc, PRIBIO | PCATCH, "tpm_getburst", 1);
    165 		if (rv && rv != EWOULDBLOCK) {
    166 			return 0;
    167 		}
    168 	}
    169 
    170 	return 0;
    171 }
    172 
    173 static inline uint8_t
    174 tpm_status(struct tpm_softc *sc)
    175 {
    176 	return bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_STS) &
    177 	    TPM_STS_STATUS_BITS;
    178 }
    179 
    180 /* -------------------------------------------------------------------------- */
    181 
    182 /*
    183  * Save TPM state on suspend. On resume we don't do anything, since the BIOS
    184  * is supposed to restore the previously saved state.
    185  */
    186 
    187 bool
    188 tpm12_suspend(device_t dev, const pmf_qual_t *qual)
    189 {
    190 	struct tpm_softc *sc = device_private(dev);
    191 	static const uint8_t command[] = {
    192 		0, 193,		/* TPM_TAG_RQU_COMMAND */
    193 		0, 0, 0, 10,	/* Length in bytes */
    194 		0, 0, 0, 156	/* TPM_ORD_SaveStates */
    195 	};
    196 	uint8_t scratch[sizeof(command)];
    197 
    198 	(*sc->sc_write)(sc, &command, sizeof(command));
    199 	(*sc->sc_read)(sc, &scratch, sizeof(scratch), NULL, 0);
    200 
    201 	return true;
    202 }
    203 
    204 bool
    205 tpm12_resume(device_t dev, const pmf_qual_t *qual)
    206 {
    207 	return true;
    208 }
    209 
    210 /* -------------------------------------------------------------------------- */
    211 
    212 /*
    213  * Wait for given status bits using polling.
    214  */
    215 static int
    216 tpm_waitfor_poll(struct tpm_softc *sc, uint8_t mask, int to, wchan_t chan)
    217 {
    218 	int rv;
    219 
    220 	while (((sc->sc_status = tpm_status(sc)) & mask) != mask && to--) {
    221 		rv = tsleep(chan, PRIBIO | PCATCH, "tpm_poll", 1);
    222 		if (rv && rv != EWOULDBLOCK) {
    223 			return rv;
    224 		}
    225 	}
    226 
    227 	return 0;
    228 }
    229 
    230 /*
    231  * Wait for given status bits using interrupts.
    232  */
    233 static int
    234 tpm_waitfor_int(struct tpm_softc *sc, uint8_t mask, int tmo, wchan_t chan,
    235     int inttype)
    236 {
    237 	int rv, to;
    238 
    239 	sc->sc_status = tpm_status(sc);
    240 	if ((sc->sc_status & mask) == mask)
    241 		return 0;
    242 
    243 	/*
    244 	 * Enable interrupt on tpm chip.  Note that interrupts on our
    245 	 * level (SPL_TTY) are disabled (see tpm{read,write} et al) and
    246 	 * will not be delivered to the cpu until we call tsleep(9) below.
    247 	 */
    248 	bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE,
    249 	    bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE) |
    250 	    inttype);
    251 	bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE,
    252 	    bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE) |
    253 	    TPM_GLOBAL_INT_ENABLE);
    254 
    255 	sc->sc_status = tpm_status(sc);
    256 	if ((sc->sc_status & mask) == mask) {
    257 		rv = 0;
    258 		goto out;
    259 	}
    260 
    261 	to = tpm_tmotohz(tmo);
    262 
    263 	/*
    264 	 * tsleep(9) enables interrupts on the cpu and returns after
    265 	 * wake up with interrupts disabled again.  Note that interrupts
    266 	 * generated by the tpm chip while being at SPL_TTY are not lost
    267 	 * but held and delivered as soon as the cpu goes below SPL_TTY.
    268 	 */
    269 	rv = tsleep(chan, PRIBIO | PCATCH, "tpm_wait", to);
    270 
    271 	sc->sc_status = tpm_status(sc);
    272 	if ((sc->sc_status & mask) == mask)
    273 		rv = 0;
    274 
    275 out:
    276 	/* Disable interrupts on tpm chip again. */
    277 	bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE,
    278 	    bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE) &
    279 	    ~TPM_GLOBAL_INT_ENABLE);
    280 	bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE,
    281 	    bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE) &
    282 	    ~inttype);
    283 
    284 	return rv;
    285 }
    286 
    287 /*
    288  * Wait on given status bits, use interrupts where possible, otherwise poll.
    289  */
    290 static int
    291 tpm_waitfor(struct tpm_softc *sc, uint8_t bits, int tmo, wchan_t chan)
    292 {
    293 	int retry, to, rv;
    294 	uint8_t todo;
    295 
    296 	/*
    297 	 * We use interrupts for TPM_STS_DATA_AVAIL and TPM_STS_VALID (if the
    298 	 * TPM chip supports them) as waiting for those can take really long.
    299 	 * The other TPM_STS* are not needed very often so we do not support
    300 	 * them.
    301 	 */
    302 	if (sc->sc_vector != -1) {
    303 		todo = bits;
    304 
    305 		/*
    306 		 * Wait for data ready. This interrupt only occurs when both
    307 		 * TPM_STS_VALID and TPM_STS_DATA_AVAIL are asserted. Thus we
    308 		 * don't have to bother with TPM_STS_VALID separately and can
    309 		 * just return.
    310 		 *
    311 		 * This only holds for interrupts! When using polling both
    312 		 * flags have to be waited for, see below.
    313 		 */
    314 		if ((bits & TPM_STS_DATA_AVAIL) &&
    315 		    (sc->sc_capabilities & TPM_INTF_DATA_AVAIL_INT))
    316 			return tpm_waitfor_int(sc, bits, tmo, chan,
    317 			    TPM_DATA_AVAIL_INT);
    318 
    319 		/* Wait for status valid bit. */
    320 		if ((bits & TPM_STS_VALID) &&
    321 		    (sc->sc_capabilities & TPM_INTF_STS_VALID_INT)) {
    322 			rv = tpm_waitfor_int(sc, bits, tmo, chan,
    323 			    TPM_STS_VALID_INT);
    324 			if (rv)
    325 				return rv;
    326 			todo = bits & ~TPM_STS_VALID;
    327 		}
    328 
    329 		/*
    330 		 * When all flags have been taken care of, return. Otherwise
    331 		 * use polling for eg TPM_STS_CMD_READY.
    332 		 */
    333 		if (todo == 0)
    334 			return 0;
    335 	}
    336 
    337 	retry = 3;
    338 
    339 restart:
    340 	/*
    341 	 * If requested, wait for TPM_STS_VALID before dealing with any other
    342 	 * flag. Eg when both TPM_STS_DATA_AVAIL and TPM_STS_VALID are
    343 	 * requested, wait for the latter first.
    344 	 */
    345 	todo = bits;
    346 	if (bits & TPM_STS_VALID)
    347 		todo = TPM_STS_VALID;
    348 	to = tpm_tmotohz(tmo);
    349 again:
    350 	if ((rv = tpm_waitfor_poll(sc, todo, to, chan)) != 0)
    351 		return rv;
    352 
    353 	if ((todo & sc->sc_status) == TPM_STS_VALID) {
    354 		/* Now wait for other flags. */
    355 		todo = bits & ~TPM_STS_VALID;
    356 		to++;
    357 		goto again;
    358 	}
    359 
    360 	if ((todo & sc->sc_status) != todo) {
    361 		if (retry-- && (bits & TPM_STS_VALID)) {
    362 			bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS,
    363 			    TPM_STS_RESP_RETRY);
    364 			goto restart;
    365 		}
    366 		return EIO;
    367 	}
    368 
    369 	return 0;
    370 }
    371 
    372 int
    373 tpm_intr(void *v)
    374 {
    375 	struct tpm_softc *sc = v;
    376 	uint32_t reg;
    377 
    378 	reg = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS);
    379 	if (!(reg & (TPM_CMD_READY_INT | TPM_LOCALITY_CHANGE_INT |
    380 	    TPM_STS_VALID_INT | TPM_DATA_AVAIL_INT)))
    381 		return 0;
    382 
    383 	if (reg & TPM_STS_VALID_INT)
    384 		wakeup(sc);
    385 	if (reg & TPM_CMD_READY_INT)
    386 		wakeup(sc->sc_write);
    387 	if (reg & TPM_DATA_AVAIL_INT)
    388 		wakeup(sc->sc_read);
    389 	if (reg & TPM_LOCALITY_CHANGE_INT)
    390 		wakeup(sc->sc_init);
    391 
    392 	bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS, reg);
    393 
    394 	return 1;
    395 }
    396 
    397 /* -------------------------------------------------------------------------- */
    398 
    399 /*
    400  * TPM using TIS 1.2 interface.
    401  */
    402 
    403 int
    404 tpm_tis12_probe(bus_space_tag_t bt, bus_space_handle_t bh)
    405 {
    406 	uint32_t cap;
    407 	uint8_t reg;
    408 	int tmo;
    409 
    410 	cap = bus_space_read_4(bt, bh, TPM_INTF_CAPABILITY);
    411 	if (cap == 0xffffffff)
    412 		return 0;
    413 	if ((cap & TPM_CAPS_REQUIRED) != TPM_CAPS_REQUIRED)
    414 		return 0;
    415 	if (!(cap & (TPM_INTF_INT_EDGE_RISING | TPM_INTF_INT_LEVEL_LOW)))
    416 		return 0;
    417 
    418 	/* Request locality 0. */
    419 	bus_space_write_1(bt, bh, TPM_ACCESS, TPM_ACCESS_REQUEST_USE);
    420 
    421 	/* Wait for it to become active. */
    422 	tmo = TPM_ACCESS_TMO; /* Milliseconds. */
    423 	while ((reg = bus_space_read_1(bt, bh, TPM_ACCESS) &
    424 	    (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
    425 	    (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY) && tmo--) {
    426 		DELAY(1000); /* 1 millisecond. */
    427 	}
    428 	if ((reg & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
    429 	    (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) {
    430 		return 0;
    431 	}
    432 
    433 	if (bus_space_read_4(bt, bh, TPM_ID) == 0xffffffff)
    434 		return 0;
    435 
    436 	return 1;
    437 }
    438 
    439 static int
    440 tpm_tis12_irqinit(struct tpm_softc *sc, int irq, int idx)
    441 {
    442 	uint32_t reg;
    443 
    444 	if ((irq == -1) || (tpm_devs[idx].flags & TPM_DEV_NOINTS)) {
    445 		sc->sc_vector = -1;
    446 		return 0;
    447 	}
    448 
    449 	/* Ack and disable all interrupts. */
    450 	reg = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE);
    451 	bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE,
    452 	    reg & ~TPM_GLOBAL_INT_ENABLE);
    453 	bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS,
    454 	    bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS));
    455 
    456 	/* Program interrupt vector. */
    457 	bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_INT_VECTOR, irq);
    458 	sc->sc_vector = irq;
    459 
    460 	/* Program interrupt type. */
    461 	reg &= ~(TPM_INT_EDGE_RISING|TPM_INT_EDGE_FALLING|TPM_INT_LEVEL_HIGH|
    462 	    TPM_INT_LEVEL_LOW);
    463 	reg |= TPM_GLOBAL_INT_ENABLE|TPM_CMD_READY_INT|TPM_LOCALITY_CHANGE_INT|
    464 	    TPM_STS_VALID_INT|TPM_DATA_AVAIL_INT;
    465 	if (sc->sc_capabilities & TPM_INTF_INT_EDGE_RISING)
    466 		reg |= TPM_INT_EDGE_RISING;
    467 	else if (sc->sc_capabilities & TPM_INTF_INT_EDGE_FALLING)
    468 		reg |= TPM_INT_EDGE_FALLING;
    469 	else if (sc->sc_capabilities & TPM_INTF_INT_LEVEL_HIGH)
    470 		reg |= TPM_INT_LEVEL_HIGH;
    471 	else
    472 		reg |= TPM_INT_LEVEL_LOW;
    473 
    474 	bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE, reg);
    475 
    476 	return 0;
    477 }
    478 
    479 int
    480 tpm_tis12_init(struct tpm_softc *sc, int irq)
    481 {
    482 	int i;
    483 
    484 	sc->sc_capabilities = bus_space_read_4(sc->sc_bt, sc->sc_bh,
    485 	    TPM_INTF_CAPABILITY);
    486 	sc->sc_devid = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_ID);
    487 	sc->sc_rev = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_REV);
    488 
    489 	for (i = 0; tpm_devs[i].devid; i++) {
    490 		if (tpm_devs[i].devid == sc->sc_devid)
    491 			break;
    492 	}
    493 
    494 	if (tpm_devs[i].devid)
    495 		aprint_normal_dev(sc->sc_dev, "%s rev 0x%x\n",
    496 		    tpm_devs[i].name, sc->sc_rev);
    497 	else
    498 		aprint_normal_dev(sc->sc_dev, "device 0x%08x rev 0x%x\n",
    499 		    sc->sc_devid, sc->sc_rev);
    500 
    501 	if (tpm_tis12_irqinit(sc, irq, i))
    502 		return 1;
    503 
    504 	if (tpm_request_locality(sc, 0))
    505 		return 1;
    506 
    507 	/* Abort whatever it thought it was doing. */
    508 	bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS, TPM_STS_CMD_READY);
    509 
    510 	return 0;
    511 }
    512 
    513 int
    514 tpm_tis12_start(struct tpm_softc *sc, int flag)
    515 {
    516 	int rv;
    517 
    518 	if (flag == UIO_READ) {
    519 		rv = tpm_waitfor(sc, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
    520 		    TPM_READ_TMO, sc->sc_read);
    521 		return rv;
    522 	}
    523 
    524 	/* Request the 0th locality. */
    525 	if ((rv = tpm_request_locality(sc, 0)) != 0)
    526 		return rv;
    527 
    528 	sc->sc_status = tpm_status(sc);
    529 	if (sc->sc_status & TPM_STS_CMD_READY)
    530 		return 0;
    531 
    532 	/* Abort previous and restart. */
    533 	bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS, TPM_STS_CMD_READY);
    534 	rv = tpm_waitfor(sc, TPM_STS_CMD_READY, TPM_READY_TMO, sc->sc_write);
    535 	if (rv)
    536 		return rv;
    537 
    538 	return 0;
    539 }
    540 
    541 int
    542 tpm_tis12_read(struct tpm_softc *sc, void *buf, size_t len, size_t *count,
    543     int flags)
    544 {
    545 	uint8_t *p = buf;
    546 	size_t cnt;
    547 	int rv, n, bcnt;
    548 
    549 	cnt = 0;
    550 	while (len > 0) {
    551 		rv = tpm_waitfor(sc, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
    552 		    TPM_READ_TMO, sc->sc_read);
    553 		if (rv)
    554 			return rv;
    555 
    556 		bcnt = tpm_getburst(sc);
    557 		n = MIN(len, bcnt);
    558 
    559 		for (; n--; len--) {
    560 			*p++ = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_DATA);
    561 			cnt++;
    562 		}
    563 
    564 		if ((flags & TPM_PARAM_SIZE) == 0 && cnt >= 6)
    565 			break;
    566 	}
    567 
    568 	if (count)
    569 		*count = cnt;
    570 
    571 	return 0;
    572 }
    573 
    574 int
    575 tpm_tis12_write(struct tpm_softc *sc, const void *buf, size_t len)
    576 {
    577 	const uint8_t *p = buf;
    578 	size_t cnt;
    579 	int rv, r;
    580 
    581 	if (len == 0)
    582 		return 0;
    583 	if ((rv = tpm_request_locality(sc, 0)) != 0)
    584 		return rv;
    585 
    586 	cnt = 0;
    587 	while (cnt < len - 1) {
    588 		for (r = tpm_getburst(sc); r > 0 && cnt < len - 1; r--) {
    589 			bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_DATA, *p++);
    590 			cnt++;
    591 		}
    592 		if ((rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, sc))) {
    593 			return rv;
    594 		}
    595 		sc->sc_status = tpm_status(sc);
    596 		if (!(sc->sc_status & TPM_STS_DATA_EXPECT)) {
    597 			return EIO;
    598 		}
    599 	}
    600 
    601 	bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_DATA, *p++);
    602 	cnt++;
    603 
    604 	if ((rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, sc))) {
    605 		return rv;
    606 	}
    607 	if ((sc->sc_status & TPM_STS_DATA_EXPECT) != 0) {
    608 		return EIO;
    609 	}
    610 
    611 	return 0;
    612 }
    613 
    614 int
    615 tpm_tis12_end(struct tpm_softc *sc, int flag, int err)
    616 {
    617 	int rv = 0;
    618 
    619 	if (flag == UIO_READ) {
    620 		rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, sc->sc_read);
    621 		if (rv)
    622 			return rv;
    623 
    624 		/* Still more data? */
    625 		sc->sc_status = tpm_status(sc);
    626 		if (!err && ((sc->sc_status & TPM_STS_DATA_AVAIL) ==
    627 		    TPM_STS_DATA_AVAIL)) {
    628 			rv = EIO;
    629 		}
    630 
    631 		bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS,
    632 		    TPM_STS_CMD_READY);
    633 
    634 		/* Release the 0th locality. */
    635 		bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS,
    636 		    TPM_ACCESS_ACTIVE_LOCALITY);
    637 	} else {
    638 		/* Hungry for more? */
    639 		sc->sc_status = tpm_status(sc);
    640 		if (!err && (sc->sc_status & TPM_STS_DATA_EXPECT)) {
    641 			rv = EIO;
    642 		}
    643 
    644 		bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS,
    645 		    err ? TPM_STS_CMD_READY : TPM_STS_GO);
    646 	}
    647 
    648 	return rv;
    649 }
    650 
    651 /* -------------------------------------------------------------------------- */
    652 
    653 static dev_type_open(tpmopen);
    654 static dev_type_close(tpmclose);
    655 static dev_type_read(tpmread);
    656 static dev_type_write(tpmwrite);
    657 static dev_type_ioctl(tpmioctl);
    658 
    659 const struct cdevsw tpm_cdevsw = {
    660 	.d_open = tpmopen,
    661 	.d_close = tpmclose,
    662 	.d_read = tpmread,
    663 	.d_write = tpmwrite,
    664 	.d_ioctl = tpmioctl,
    665 	.d_stop = nostop,
    666 	.d_tty = notty,
    667 	.d_poll = nopoll,
    668 	.d_mmap = nommap,
    669 	.d_kqfilter = nokqfilter,
    670 	.d_discard = nodiscard,
    671 	.d_flag = D_OTHER,
    672 };
    673 
    674 #define TPMUNIT(a)	minor(a)
    675 
    676 static int
    677 tpmopen(dev_t dev, int flag, int mode, struct lwp *l)
    678 {
    679 	struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev));
    680 
    681 	if (sc == NULL)
    682 		return ENXIO;
    683 	if (sc->sc_flags & TPM_OPEN)
    684 		return EBUSY;
    685 
    686 	sc->sc_flags |= TPM_OPEN;
    687 
    688 	return 0;
    689 }
    690 
    691 static int
    692 tpmclose(dev_t dev, int flag, int mode, struct lwp *l)
    693 {
    694 	struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev));
    695 
    696 	if (sc == NULL)
    697 		return ENXIO;
    698 	if (!(sc->sc_flags & TPM_OPEN))
    699 		return EINVAL;
    700 
    701 	sc->sc_flags &= ~TPM_OPEN;
    702 
    703 	return 0;
    704 }
    705 
    706 static int
    707 tpmread(dev_t dev, struct uio *uio, int flags)
    708 {
    709 	struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev));
    710 	uint8_t buf[TPM_BUFSIZ], *p;
    711 	size_t cnt, len, n;
    712 	int  rv, s;
    713 
    714 	if (sc == NULL)
    715 		return ENXIO;
    716 
    717 	s = spltty();
    718 	if ((rv = (*sc->sc_start)(sc, UIO_READ)))
    719 		goto out;
    720 
    721 	if ((rv = (*sc->sc_read)(sc, buf, TPM_HDRSIZE, &cnt, 0))) {
    722 		(*sc->sc_end)(sc, UIO_READ, rv);
    723 		goto out;
    724 	}
    725 
    726 	len = (buf[2] << 24) | (buf[3] << 16) | (buf[4] << 8) | buf[5];
    727 	if (len > uio->uio_resid) {
    728 		rv = EIO;
    729 		(*sc->sc_end)(sc, UIO_READ, rv);
    730 		goto out;
    731 	}
    732 
    733 	/* Copy out header. */
    734 	if ((rv = uiomove(buf, cnt, uio))) {
    735 		(*sc->sc_end)(sc, UIO_READ, rv);
    736 		goto out;
    737 	}
    738 
    739 	/* Get remaining part of the answer (if anything is left). */
    740 	for (len -= cnt, p = buf, n = sizeof(buf); len > 0; p = buf, len -= n,
    741 	    n = sizeof(buf)) {
    742 		n = MIN(n, len);
    743 		if ((rv = (*sc->sc_read)(sc, p, n, NULL, TPM_PARAM_SIZE))) {
    744 			(*sc->sc_end)(sc, UIO_READ, rv);
    745 			goto out;
    746 		}
    747 		p += n;
    748 		if ((rv = uiomove(buf, p - buf, uio))) {
    749 			(*sc->sc_end)(sc, UIO_READ, rv);
    750 			goto out;
    751 		}
    752 	}
    753 
    754 	rv = (*sc->sc_end)(sc, UIO_READ, rv);
    755 out:
    756 	splx(s);
    757 	return rv;
    758 }
    759 
    760 static int
    761 tpmwrite(dev_t dev, struct uio *uio, int flags)
    762 {
    763 	struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev));
    764 	uint8_t buf[TPM_BUFSIZ];
    765 	int n, rv, s;
    766 
    767 	if (sc == NULL)
    768 		return ENXIO;
    769 
    770 	s = spltty();
    771 
    772 	n = MIN(sizeof(buf), uio->uio_resid);
    773 	if ((rv = uiomove(buf, n, uio))) {
    774 		goto out;
    775 	}
    776 	if ((rv = (*sc->sc_start)(sc, UIO_WRITE))) {
    777 		goto out;
    778 	}
    779 	if ((rv = (*sc->sc_write)(sc, buf, n))) {
    780 		goto out;
    781 	}
    782 
    783 	rv = (*sc->sc_end)(sc, UIO_WRITE, rv);
    784 out:
    785 	splx(s);
    786 	return rv;
    787 }
    788 
    789 static int
    790 tpmioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
    791 {
    792 	struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev));
    793 	struct tpm_ioc_getinfo *info;
    794 
    795 	if (sc == NULL)
    796 		return ENXIO;
    797 
    798 	switch (cmd) {
    799 	case TPM_IOC_GETINFO:
    800 		info = addr;
    801 		info->api_version = TPM_API_VERSION;
    802 		info->tpm_version = sc->sc_ver;
    803 		info->device_id = sc->sc_devid;
    804 		info->device_rev = sc->sc_rev;
    805 		info->device_caps = sc->sc_capabilities;
    806 		return 0;
    807 	default:
    808 		break;
    809 	}
    810 
    811 	return ENOTTY;
    812 }
    813