Tue Oct 8 18:43:03 2019 UTC ()
Improvements in tpm(4):
 - Remove interrupt support, do polling only, avoids unnecessary trouble.
 - Simplify a few things.
 - Fix the suspend function, the SaveState command is 0x98, not 0x9C.
 - Make the driver MP-safe.
 - Sync the man page with reality.


(maxv)
diff -r1.4 -r1.5 src/share/man/man4/tpm.4
diff -r1.8 -r1.9 src/sys/dev/acpi/tpm_acpi.c
diff -r1.13 -r1.14 src/sys/dev/ic/tpm.c
diff -r1.4 -r1.5 src/sys/dev/ic/tpmreg.h
diff -r1.4 -r1.5 src/sys/dev/ic/tpmvar.h
diff -r1.4 -r1.5 src/sys/dev/isa/tpm_isa.c

cvs diff -r1.4 -r1.5 src/share/man/man4/tpm.4 (expand / switch to unified diff)

--- src/share/man/man4/tpm.4 2018/02/22 01:40:49 1.4
+++ src/share/man/man4/tpm.4 2019/10/08 18:43:03 1.5
@@ -1,69 +1,65 @@ @@ -1,69 +1,65 @@
1.\" $NetBSD: tpm.4,v 1.4 2018/02/22 01:40:49 pgoyette Exp $ 1.\" $NetBSD: tpm.4,v 1.5 2019/10/08 18:43:03 maxv Exp $
2.\" 2.\"
3.\" Copyright (c) 2010 Hans-Jörg Höxer, <Hans-Joerg.Hoexer@genua.de> 3.\" Copyright (c) 2019 The NetBSD Foundation, Inc.
 4.\" All rights reserved.
4.\" 5.\"
5.\" Permission to use, copy, modify, and distribute this software for any 6.\" This code is derived from software contributed to The NetBSD Foundation
6.\" purpose with or without fee is hereby granted, provided that the above 7.\" by Maxime Villard.
7.\" copyright notice and this permission notice appear in all copies. 
8.\" 8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9.\" Redistribution and use in source and binary forms, with or without
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10.\" modification, are permitted provided that the following conditions
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11.\" are met:
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12.\" 1. Redistributions of source code must retain the above copyright
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13.\" notice, this list of conditions and the following disclaimer.
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14.\" 2. Redistributions in binary form must reproduce the above copyright
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15.\" notice, this list of conditions and the following disclaimer in the
 16.\" documentation and/or other materials provided with the distribution.
16.\" 17.\"
17.Dd February 22, 2018 18.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 19.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 20.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 21.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 22.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 23.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 24.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 25.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 26.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 27.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 28.\" POSSIBILITY OF SUCH DAMAGE.
 29.\"
 30.Dd October 6, 2019
18.Dt TPM 4 31.Dt TPM 4
19.Os 32.Os
20.Sh NAME 33.Sh NAME
21.Nm tpm 34.Nm tpm
22.Nd Trusted Platform Module 35.Nd Trusted Platform Module
23.Sh SYNOPSIS 36.Sh SYNOPSIS
24.Cd "tpm* at isa? iomem 0xfed40000" 37.Cd "tpm* at isa? iomem 0xfed40000"
25.Cd "tpm* at isa? iomem 0xfed40000 irq 7" 
26.Cd "tpm* at acpi?" 38.Cd "tpm* at acpi?"
27.Sh DESCRIPTION 39.Sh DESCRIPTION
28The 40The
29.Nm 41.Nm
30driver provides support for various trusted platform modules (TPM) that can 42driver provides support for various Trusted Platform Module (TPM) chips.
31store cryptographic keys. 
32.Pp 43.Pp
33Supported modules: 44Supported modules:
34.Pp 45.Pp
35.Bl -bullet -compact -offset indent 46.Bl -bullet -compact -offset indent
36.It 47.It
37Atmel 97SC3203 48TPM 2.0 chips over ACPI
38.It 
39Broadcom BCM0102 
40.It 
41Infineon IFX SLD 9630 TT 1.1 and IFX SLB 9635 TT 1.2 
42.It 
43Intel INTC0102 
44.It 
45Sinosun SNS SSX35 
46.It 
47STM ST19WP18 
48.It 49.It
49Winbond WEC WPCT200 50TPM 1.2 chips over ISA
50.El 51.El
51.Pp 52.Pp
52The driver can be configured to use an IRQ by providing a free ISA 53Note that the supported interface version is TIS1.2 in each case.
53interrupt vector using the keyword 
54.Em irq 
55in the kernel configuration file or using 
56.Xr config 1 . 
57If not IRQ is specified, the driver uses polling. 
58This is the default configuration. 
59.Sh SEE ALSO 54.Sh SEE ALSO
60.Xr config 1 , 55.Xr config 1 ,
61.Xr intro 4 56.Xr intro 4
62.Sh AUTHORS 57.Sh AUTHORS
63.An -nosplit 58.An -nosplit
64The 59The
65.Nm 60.Nm
66driver was written by 61driver was written by
 62.An Maxime Villard ,
67.An Michael Shalayeff 63.An Michael Shalayeff
68and 64and
69.An Hans-Joerg Hoexer . 65.An Hans-Joerg Hoexer .

cvs diff -r1.8 -r1.9 src/sys/dev/acpi/tpm_acpi.c (expand / switch to unified diff)

--- src/sys/dev/acpi/tpm_acpi.c 2019/06/22 12:57:40 1.8
+++ src/sys/dev/acpi/tpm_acpi.c 2019/10/08 18:43:02 1.9
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: tpm_acpi.c,v 1.8 2019/06/22 12:57:40 maxv Exp $ */ 1/* $NetBSD: tpm_acpi.c,v 1.9 2019/10/08 18:43:02 maxv Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2012, 2019 The NetBSD Foundation, Inc. 4 * Copyright (c) 2012, 2019 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christos Zoulas and Maxime Villard. 8 * by Christos Zoulas and Maxime Villard.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -20,43 +20,40 @@ @@ -20,43 +20,40 @@
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 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 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 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 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: tpm_acpi.c,v 1.8 2019/06/22 12:57:40 maxv Exp $"); 33__KERNEL_RCSID(0, "$NetBSD: tpm_acpi.c,v 1.9 2019/10/08 18:43:02 maxv Exp $");
34 34
35#include <sys/param.h> 35#include <sys/param.h>
36#include <sys/device.h> 
37#include <sys/systm.h> 36#include <sys/systm.h>
38#include <sys/device.h> 37#include <sys/device.h>
39#include <sys/bus.h> 38#include <sys/bus.h>
40#include <sys/pmf.h> 39#include <sys/pmf.h>
41 40
42#include <dev/ic/tpmreg.h> 41#include <dev/ic/tpmreg.h>
43#include <dev/ic/tpmvar.h> 42#include <dev/ic/tpmvar.h>
44 43
45#include <dev/acpi/acpireg.h> 44#include <dev/acpi/acpireg.h>
46#include <dev/acpi/acpivar.h> 45#include <dev/acpi/acpivar.h>
47 46
48#include <dev/isa/isavar.h> 
49 
50#include "ioconf.h" 47#include "ioconf.h"
51 48
52#define _COMPONENT ACPI_RESOURCE_COMPONENT 49#define _COMPONENT ACPI_RESOURCE_COMPONENT
53ACPI_MODULE_NAME ("tpm_acpi") 50ACPI_MODULE_NAME ("tpm_acpi")
54 51
55static int tpm_acpi_match(device_t, cfdata_t, void *); 52static int tpm_acpi_match(device_t, cfdata_t, void *);
56static void tpm_acpi_attach(device_t, device_t, void *); 53static void tpm_acpi_attach(device_t, device_t, void *);
57 54
58CFATTACH_DECL_NEW(tpm_acpi, sizeof(struct tpm_softc), tpm_acpi_match, 55CFATTACH_DECL_NEW(tpm_acpi, sizeof(struct tpm_softc), tpm_acpi_match,
59 tpm_acpi_attach, NULL, NULL); 56 tpm_acpi_attach, NULL, NULL);
60 57
61/* 58/*
62 * Supported TPM 2.0 devices. 59 * Supported TPM 2.0 devices.
@@ -90,85 +87,72 @@ tpm_acpi_match(device_t parent, cfdata_t @@ -90,85 +87,72 @@ tpm_acpi_match(device_t parent, cfdata_t
90 if (tpm2->StartMethod != ACPI_TPM2_MEMORY_MAPPED) 87 if (tpm2->StartMethod != ACPI_TPM2_MEMORY_MAPPED)
91 return 0; 88 return 0;
92 89
93 return 1; 90 return 1;
94} 91}
95 92
96static void 93static void
97tpm_acpi_attach(device_t parent, device_t self, void *aux) 94tpm_acpi_attach(device_t parent, device_t self, void *aux)
98{ 95{
99 struct tpm_softc *sc = device_private(self); 96 struct tpm_softc *sc = device_private(self);
100 struct acpi_attach_args *aa = aux; 97 struct acpi_attach_args *aa = aux;
101 struct acpi_resources res; 98 struct acpi_resources res;
102 struct acpi_mem *mem; 99 struct acpi_mem *mem;
103 struct acpi_irq *irq; 
104 bus_addr_t base; 100 bus_addr_t base;
105 bus_addr_t size; 101 bus_addr_t size;
106 int rv, inum; 102 int rv;
107 
108 sc->sc_dev = self; 
109 sc->sc_ver = TPM_2_0; 
110 103
111 rv = acpi_resource_parse(self, aa->aa_node->ad_handle, "_CRS", &res, 104 rv = acpi_resource_parse(self, aa->aa_node->ad_handle, "_CRS", &res,
112 &acpi_resource_parse_ops_default); 105 &acpi_resource_parse_ops_default);
113 if (ACPI_FAILURE(rv)) { 106 if (ACPI_FAILURE(rv)) {
114 aprint_error_dev(sc->sc_dev, "cannot parse resources %d\n", rv); 107 aprint_error_dev(self, "cannot parse resources %d\n", rv);
115 return; 108 return;
116 } 109 }
117 110
118 mem = acpi_res_mem(&res, 0); 111 mem = acpi_res_mem(&res, 0);
119 if (mem == NULL) { 112 if (mem == NULL) {
120 aprint_error_dev(sc->sc_dev, "cannot find mem\n"); 113 aprint_error_dev(self, "cannot find mem\n");
121 goto out; 114 goto out;
122 } 115 }
123 if (mem->ar_length != TPM_SPACE_SIZE) { 116 if (mem->ar_length != TPM_SPACE_SIZE) {
124 aprint_error_dev(sc->sc_dev, 117 aprint_error_dev(self, "wrong size mem %"PRIu64" != %u\n",
125 "wrong size mem %"PRIu64" != %u\n", 
126 (uint64_t)mem->ar_length, TPM_SPACE_SIZE); 118 (uint64_t)mem->ar_length, TPM_SPACE_SIZE);
127 goto out; 119 goto out;
128 } 120 }
129 121
130 base = mem->ar_base; 122 sc->sc_dev = self;
131 size = mem->ar_length; 123 sc->sc_ver = TPM_2_0;
132 sc->sc_bt = aa->aa_memt; 124 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
 125 sc->sc_busy = false;
133 sc->sc_init = tpm_tis12_init; 126 sc->sc_init = tpm_tis12_init;
134 sc->sc_start = tpm_tis12_start; 127 sc->sc_start = tpm_tis12_start;
135 sc->sc_read = tpm_tis12_read; 128 sc->sc_read = tpm_tis12_read;
136 sc->sc_write = tpm_tis12_write; 129 sc->sc_write = tpm_tis12_write;
137 sc->sc_end = tpm_tis12_end; 130 sc->sc_end = tpm_tis12_end;
 131 sc->sc_bt = aa->aa_memt;
 132
 133 base = mem->ar_base;
 134 size = mem->ar_length;
138 135
139 if (bus_space_map(sc->sc_bt, base, size, 0, &sc->sc_bh)) { 136 if (bus_space_map(sc->sc_bt, base, size, 0, &sc->sc_bh)) {
140 aprint_error_dev(sc->sc_dev, "cannot map registers\n"); 137 aprint_error_dev(sc->sc_dev, "cannot map registers\n");
141 goto out; 138 goto out;
142 } 139 }
143 140
144 if (!tpm_tis12_probe(sc->sc_bt, sc->sc_bh)) { 141 if (!tpm_tis12_probe(sc->sc_bt, sc->sc_bh)) {
145 aprint_error_dev(sc->sc_dev, "TIS1.2 probe failed\n"); 142 aprint_error_dev(sc->sc_dev, "TIS1.2 probe failed\n");
146 goto out1; 143 goto out1;
147 } 144 }
148 145
149 irq = acpi_res_irq(&res, 0); 146 if ((*sc->sc_init)(sc) != 0) {
150 if (irq == NULL) 
151 inum = -1; 
152 else 
153 inum = irq->ar_irq; 
154 
155 if ((rv = (*sc->sc_init)(sc, inum)) != 0) { 
156 aprint_error_dev(sc->sc_dev, "cannot init device %d\n", rv); 147 aprint_error_dev(sc->sc_dev, "cannot init device %d\n", rv);
157 goto out1; 148 goto out1;
158 } 149 }
159 150
160 if (inum != -1 && 
161 (sc->sc_ih = isa_intr_establish(aa->aa_ic, irq->ar_irq, 
162 IST_EDGE, IPL_TTY, tpm_intr, sc)) == NULL) { 
163 aprint_error_dev(sc->sc_dev, "cannot establish interrupt\n"); 
164 goto out1; 
165 } 
166 
167 acpi_resource_cleanup(&res); 151 acpi_resource_cleanup(&res);
168 return; 152 return;
169 153
170out1: 154out1:
171 bus_space_unmap(sc->sc_bt, sc->sc_bh, size); 155 bus_space_unmap(sc->sc_bt, sc->sc_bh, size);
172out: 156out:
173 acpi_resource_cleanup(&res); 157 acpi_resource_cleanup(&res);
174} 158}

cvs diff -r1.13 -r1.14 src/sys/dev/ic/tpm.c (expand / switch to unified diff)

--- src/sys/dev/ic/tpm.c 2019/06/22 12:57:41 1.13
+++ src/sys/dev/ic/tpm.c 2019/10/08 18:43:02 1.14
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: tpm.c,v 1.13 2019/06/22 12:57:41 maxv Exp $ */ 1/* $NetBSD: tpm.c,v 1.14 2019/10/08 18:43:02 maxv Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2019 The NetBSD Foundation, Inc. 4 * Copyright (c) 2019 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Maxime Villard. 8 * by Maxime Villard.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -38,74 +38,58 @@ @@ -38,74 +38,58 @@
38 * purpose with or without fee is hereby granted, provided that the above 38 * purpose with or without fee is hereby granted, provided that the above
39 * copyright notice and this permission notice appear in all copies. 39 * copyright notice and this permission notice appear in all copies.
40 * 40 *
41 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 41 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
42 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 42 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
43 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 43 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
44 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 44 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
45 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN 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 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. 47 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
48 */ 48 */
49 49
50#include <sys/cdefs.h> 50#include <sys/cdefs.h>
51__KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.13 2019/06/22 12:57:41 maxv Exp $"); 51__KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.14 2019/10/08 18:43:02 maxv Exp $");
52 52
53#include <sys/param.h> 53#include <sys/param.h>
54#include <sys/systm.h> 54#include <sys/systm.h>
55#include <sys/kernel.h> 55#include <sys/kernel.h>
56#include <sys/malloc.h> 56#include <sys/malloc.h>
57#include <sys/proc.h> 57#include <sys/proc.h>
58#include <sys/device.h> 58#include <sys/device.h>
59#include <sys/conf.h> 59#include <sys/conf.h>
60#include <sys/bus.h> 60#include <sys/bus.h>
61#include <sys/pmf.h> 61#include <sys/pmf.h>
62 62
63#include <dev/ic/tpmreg.h> 63#include <dev/ic/tpmreg.h>
64#include <dev/ic/tpmvar.h> 64#include <dev/ic/tpmvar.h>
65 65
66#include "ioconf.h" 66#include "ioconf.h"
67 67
68#define TPM_BUFSIZ 1024 68#define TPM_BUFSIZ 1024
69#define TPM_HDRSIZE 10 69#define TPM_HDRSIZE 10
 70
70#define TPM_PARAM_SIZE 0x0001 /* that's a flag */ 71#define TPM_PARAM_SIZE 0x0001 /* that's a flag */
71 72
72/* Timeouts. */ 73/* Timeouts. */
73#define TPM_ACCESS_TMO 2000 /* 2sec */ 74#define TPM_ACCESS_TMO 2000 /* 2sec */
74#define TPM_READY_TMO 2000 /* 2sec */ 75#define TPM_READY_TMO 2000 /* 2sec */
75#define TPM_READ_TMO 2000 /* 2sec */ 76#define TPM_READ_TMO 2000 /* 2sec */
76#define TPM_BURST_TMO 2000 /* 2sec */ 77#define TPM_BURST_TMO 2000 /* 2sec */
77 78
78#define TPM_CAPS_REQUIRED \ 79#define TPM_CAPS_REQUIRED \
79 (TPM_INTF_DATA_AVAIL_INT|TPM_INTF_LOCALITY_CHANGE_INT| \ 80 (TPM_INTF_DATA_AVAIL_INT|TPM_INTF_LOCALITY_CHANGE_INT| \
80 TPM_INTF_INT_LEVEL_LOW) 81 TPM_INTF_INT_LEVEL_LOW)
81 82
82static 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 
99static inline int 83static inline int
100tpm_tmotohz(int tmo) 84tpm_tmotohz(int tmo)
101{ 85{
102 struct timeval tv; 86 struct timeval tv;
103 87
104 tv.tv_sec = tmo / 1000; 88 tv.tv_sec = tmo / 1000;
105 tv.tv_usec = 1000 * (tmo % 1000); 89 tv.tv_usec = 1000 * (tmo % 1000);
106 90
107 return tvtohz(&tv); 91 return tvtohz(&tv);
108} 92}
109 93
110static int 94static int
111tpm_request_locality(struct tpm_softc *sc, int l) 95tpm_request_locality(struct tpm_softc *sc, int l)
@@ -119,27 +103,27 @@ tpm_request_locality(struct tpm_softc *s @@ -119,27 +103,27 @@ tpm_request_locality(struct tpm_softc *s
119 if ((bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS) & 103 if ((bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS) &
120 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) == 104 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) ==
121 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) 105 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY))
122 return 0; 106 return 0;
123 107
124 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS, 108 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS,
125 TPM_ACCESS_REQUEST_USE); 109 TPM_ACCESS_REQUEST_USE);
126 110
127 to = tpm_tmotohz(TPM_ACCESS_TMO); 111 to = tpm_tmotohz(TPM_ACCESS_TMO);
128 112
129 while ((r = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS) & 113 while ((r = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS) &
130 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) != 114 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
131 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY) && to--) { 115 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY) && to--) {
132 rv = tsleep(sc->sc_init, PRIBIO | PCATCH, "tpm_locality", 1); 116 rv = tsleep(sc->sc_init, PCATCH, "tpm_locality", 1);
133 if (rv && rv != EWOULDBLOCK) { 117 if (rv && rv != EWOULDBLOCK) {
134 return rv; 118 return rv;
135 } 119 }
136 } 120 }
137 121
138 if ((r & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) != 122 if ((r & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
139 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) { 123 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) {
140 return EBUSY; 124 return EBUSY;
141 } 125 }
142 126
143 return 0; 127 return 0;
144} 128}
145 129
@@ -151,27 +135,27 @@ tpm_getburst(struct tpm_softc *sc) @@ -151,27 +135,27 @@ tpm_getburst(struct tpm_softc *sc)
151 to = tpm_tmotohz(TPM_BURST_TMO); 135 to = tpm_tmotohz(TPM_BURST_TMO);
152 136
153 while (to--) { 137 while (to--) {
154 /* 138 /*
155 * Burst count is in bits 23:8, so read the two higher bytes. 139 * Burst count is in bits 23:8, so read the two higher bytes.
156 */ 140 */
157 burst = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_STS + 1); 141 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) 142 burst |= bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_STS + 2)
159 << 8; 143 << 8;
160 144
161 if (burst) 145 if (burst)
162 return burst; 146 return burst;
163 147
164 rv = tsleep(sc, PRIBIO | PCATCH, "tpm_getburst", 1); 148 rv = tsleep(sc, PCATCH, "tpm_getburst", 1);
165 if (rv && rv != EWOULDBLOCK) { 149 if (rv && rv != EWOULDBLOCK) {
166 return 0; 150 return 0;
167 } 151 }
168 } 152 }
169 153
170 return 0; 154 return 0;
171} 155}
172 156
173static inline uint8_t 157static inline uint8_t
174tpm_status(struct tpm_softc *sc) 158tpm_status(struct tpm_softc *sc)
175{ 159{
176 return bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_STS) & 160 return bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_STS) &
177 TPM_STS_STATUS_BITS; 161 TPM_STS_STATUS_BITS;
@@ -179,353 +163,163 @@ tpm_status(struct tpm_softc *sc) @@ -179,353 +163,163 @@ tpm_status(struct tpm_softc *sc)
179 163
180/* -------------------------------------------------------------------------- */ 164/* -------------------------------------------------------------------------- */
181 165
182/* 166/*
183 * Save TPM state on suspend. On resume we don't do anything, since the BIOS 167 * Save TPM state on suspend. On resume we don't do anything, since the BIOS
184 * is supposed to restore the previously saved state. 168 * is supposed to restore the previously saved state.
185 */ 169 */
186 170
187bool 171bool
188tpm12_suspend(device_t dev, const pmf_qual_t *qual) 172tpm12_suspend(device_t dev, const pmf_qual_t *qual)
189{ 173{
190 struct tpm_softc *sc = device_private(dev); 174 struct tpm_softc *sc = device_private(dev);
191 static const uint8_t command[] = { 175 static const uint8_t command[] = {
192 0, 193, /* TPM_TAG_RQU_COMMAND */ 176 0, 0xC1, /* TPM_TAG_RQU_COMMAND */
193 0, 0, 0, 10, /* Length in bytes */ 177 0, 0, 0, 10, /* Length in bytes */
194 0, 0, 0, 156 /* TPM_ORD_SaveStates */ 178 0, 0, 0, 0x98 /* TPM_ORD_SaveState */
195 }; 179 };
196 uint8_t scratch[sizeof(command)]; 180 uint8_t scratch[sizeof(command)];
197 181
198 (*sc->sc_write)(sc, &command, sizeof(command)); 182 (*sc->sc_write)(sc, &command, sizeof(command));
199 (*sc->sc_read)(sc, &scratch, sizeof(scratch), NULL, 0); 183 (*sc->sc_read)(sc, &scratch, sizeof(scratch), NULL, 0);
200 184
201 return true; 185 return true;
202} 186}
203 187
204bool 188bool
205tpm12_resume(device_t dev, const pmf_qual_t *qual) 189tpm12_resume(device_t dev, const pmf_qual_t *qual)
206{ 190{
207 return true; 191 return true;
208} 192}
209 193
210/* -------------------------------------------------------------------------- */ 194/* -------------------------------------------------------------------------- */
211 195
212/* 
213 * Wait for given status bits using polling. 
214 */ 
215static int 196static int
216tpm_waitfor_poll(struct tpm_softc *sc, uint8_t mask, int to, wchan_t chan) 197tpm_poll(struct tpm_softc *sc, uint8_t mask, int to, wchan_t chan)
217{ 198{
218 int rv; 199 int rv;
219 200
220 while (((sc->sc_status = tpm_status(sc)) & mask) != mask && to--) { 201 while (((sc->sc_status = tpm_status(sc)) & mask) != mask && to--) {
221 rv = tsleep(chan, PRIBIO | PCATCH, "tpm_poll", 1); 202 rv = tsleep(chan, PCATCH, "tpm_poll", 1);
222 if (rv && rv != EWOULDBLOCK) { 203 if (rv && rv != EWOULDBLOCK) {
223 return rv; 204 return rv;
224 } 205 }
225 } 206 }
226 207
227 return 0; 208 return 0;
228} 209}
229 210
230/* 
231 * Wait for given status bits using interrupts. 
232 */ 
233static int 
234tpm_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 
275out: 
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 */ 
290static int 211static int
291tpm_waitfor(struct tpm_softc *sc, uint8_t bits, int tmo, wchan_t chan) 212tpm_waitfor(struct tpm_softc *sc, uint8_t bits, int tmo, wchan_t chan)
292{ 213{
293 int retry, to, rv; 214 int retry, to, rv;
294 uint8_t todo; 215 uint8_t todo;
295 216
296 /* 217 to = tpm_tmotohz(tmo);
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; 218 retry = 3;
338 219
339restart: 220restart:
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; 221 todo = bits;
346 if (bits & TPM_STS_VALID) 
347 todo = TPM_STS_VALID; 
348 to = tpm_tmotohz(tmo); 
349again: 
350 if ((rv = tpm_waitfor_poll(sc, todo, to, chan)) != 0) 
351 return rv; 
352 222
353 if ((todo & sc->sc_status) == TPM_STS_VALID) { 223 /*
354 /* Now wait for other flags. */ 224 * TPM_STS_VALID has priority over the others.
355 todo = bits & ~TPM_STS_VALID; 225 */
356 to++; 226 if (todo & TPM_STS_VALID) {
357 goto again; 227 if ((rv = tpm_poll(sc, TPM_STS_VALID, to+1, chan)) != 0)
 228 return rv;
 229 todo &= ~TPM_STS_VALID;
358 } 230 }
359 231
 232 if ((rv = tpm_poll(sc, todo, to, chan)) != 0)
 233 return rv;
 234
360 if ((todo & sc->sc_status) != todo) { 235 if ((todo & sc->sc_status) != todo) {
361 if (retry-- && (bits & TPM_STS_VALID)) { 236 if ((retry-- > 0) && (bits & TPM_STS_VALID)) {
362 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS, 237 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS,
363 TPM_STS_RESP_RETRY); 238 TPM_STS_RESP_RETRY);
364 goto restart; 239 goto restart;
365 } 240 }
366 return EIO; 241 return EIO;
367 } 242 }
368 243
369 return 0; 244 return 0;
370} 245}
371 246
372int 
373tpm_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/* -------------------------------------------------------------------------- */ 247/* -------------------------------------------------------------------------- */
398 248
399/* 249/*
400 * TPM using TIS 1.2 interface. 250 * TPM using TIS 1.2 interface.
401 */ 251 */
402 252
403int 253int
404tpm_tis12_probe(bus_space_tag_t bt, bus_space_handle_t bh) 254tpm_tis12_probe(bus_space_tag_t bt, bus_space_handle_t bh)
405{ 255{
406 uint32_t cap; 256 uint32_t cap;
407 uint8_t reg; 257 uint8_t reg;
408 int tmo; 258 int tmo;
409 259
410 cap = bus_space_read_4(bt, bh, TPM_INTF_CAPABILITY); 260 cap = bus_space_read_4(bt, bh, TPM_INTF_CAPABILITY);
411 if (cap == 0xffffffff) 261 if (cap == 0xffffffff)
412 return 0; 262 return 0;
413 if ((cap & TPM_CAPS_REQUIRED) != TPM_CAPS_REQUIRED) 263 if ((cap & TPM_CAPS_REQUIRED) != TPM_CAPS_REQUIRED)
414 return 0; 264 return 0;
415 if (!(cap & (TPM_INTF_INT_EDGE_RISING | TPM_INTF_INT_LEVEL_LOW))) 
416 return 0; 
417 265
418 /* Request locality 0. */ 266 /* Request locality 0. */
419 bus_space_write_1(bt, bh, TPM_ACCESS, TPM_ACCESS_REQUEST_USE); 267 bus_space_write_1(bt, bh, TPM_ACCESS, TPM_ACCESS_REQUEST_USE);
420 268
421 /* Wait for it to become active. */ 269 /* Wait for it to become active. */
422 tmo = TPM_ACCESS_TMO; /* Milliseconds. */ 270 tmo = TPM_ACCESS_TMO; /* Milliseconds. */
423 while ((reg = bus_space_read_1(bt, bh, TPM_ACCESS) & 271 while ((reg = bus_space_read_1(bt, bh, TPM_ACCESS) &
424 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) != 272 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
425 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY) && tmo--) { 273 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY) && tmo--) {
426 DELAY(1000); /* 1 millisecond. */ 274 DELAY(1000); /* 1 millisecond. */
427 } 275 }
428 if ((reg & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) != 276 if ((reg & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
429 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) { 277 (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) {
430 return 0; 278 return 0;
431 } 279 }
432 280
433 if (bus_space_read_4(bt, bh, TPM_ID) == 0xffffffff) 281 if (bus_space_read_4(bt, bh, TPM_ID) == 0xffffffff)
434 return 0; 282 return 0;
435 283
436 return 1; 284 return 1;
437} 285}
438 286
439static int 
440tpm_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 
479int 287int
480tpm_tis12_init(struct tpm_softc *sc, int irq) 288tpm_tis12_init(struct tpm_softc *sc)
481{ 289{
482 int i; 290 sc->sc_caps = bus_space_read_4(sc->sc_bt, sc->sc_bh,
483 
484 sc->sc_capabilities = bus_space_read_4(sc->sc_bt, sc->sc_bh, 
485 TPM_INTF_CAPABILITY); 291 TPM_INTF_CAPABILITY);
486 sc->sc_devid = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_ID); 292 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); 293 sc->sc_rev = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_REV);
488 294
489 for (i = 0; tpm_devs[i].devid; i++) { 295 aprint_normal_dev(sc->sc_dev, "device 0x%08x rev 0x%x\n",
490 if (tpm_devs[i].devid == sc->sc_devid) 296 sc->sc_devid, sc->sc_rev);
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 297
504 if (tpm_request_locality(sc, 0)) 298 if (tpm_request_locality(sc, 0))
505 return 1; 299 return 1;
506 300
507 /* Abort whatever it thought it was doing. */ 301 /* Abort whatever it thought it was doing. */
508 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS, TPM_STS_CMD_READY); 302 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS, TPM_STS_CMD_READY);
509 303
510 return 0; 304 return 0;
511} 305}
512 306
513int 307int
514tpm_tis12_start(struct tpm_softc *sc, int flag) 308tpm_tis12_start(struct tpm_softc *sc, int rw)
515{ 309{
516 int rv; 310 int rv;
517 311
518 if (flag == UIO_READ) { 312 if (rw == UIO_READ) {
519 rv = tpm_waitfor(sc, TPM_STS_DATA_AVAIL | TPM_STS_VALID, 313 rv = tpm_waitfor(sc, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
520 TPM_READ_TMO, sc->sc_read); 314 TPM_READ_TMO, sc->sc_read);
521 return rv; 315 return rv;
522 } 316 }
523 317
524 /* Request the 0th locality. */ 318 /* Request the 0th locality. */
525 if ((rv = tpm_request_locality(sc, 0)) != 0) 319 if ((rv = tpm_request_locality(sc, 0)) != 0)
526 return rv; 320 return rv;
527 321
528 sc->sc_status = tpm_status(sc); 322 sc->sc_status = tpm_status(sc);
529 if (sc->sc_status & TPM_STS_CMD_READY) 323 if (sc->sc_status & TPM_STS_CMD_READY)
530 return 0; 324 return 0;
531 325
@@ -534,41 +328,41 @@ tpm_tis12_start(struct tpm_softc *sc, in @@ -534,41 +328,41 @@ tpm_tis12_start(struct tpm_softc *sc, in
534 rv = tpm_waitfor(sc, TPM_STS_CMD_READY, TPM_READY_TMO, sc->sc_write); 328 rv = tpm_waitfor(sc, TPM_STS_CMD_READY, TPM_READY_TMO, sc->sc_write);
535 if (rv) 329 if (rv)
536 return rv; 330 return rv;
537 331
538 return 0; 332 return 0;
539} 333}
540 334
541int 335int
542tpm_tis12_read(struct tpm_softc *sc, void *buf, size_t len, size_t *count, 336tpm_tis12_read(struct tpm_softc *sc, void *buf, size_t len, size_t *count,
543 int flags) 337 int flags)
544{ 338{
545 uint8_t *p = buf; 339 uint8_t *p = buf;
546 size_t cnt; 340 size_t cnt;
547 int rv, n, bcnt; 341 int rv, n;
548 342
549 cnt = 0; 343 cnt = 0;
550 while (len > 0) { 344 while (len > 0) {
551 rv = tpm_waitfor(sc, TPM_STS_DATA_AVAIL | TPM_STS_VALID, 345 rv = tpm_waitfor(sc, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
552 TPM_READ_TMO, sc->sc_read); 346 TPM_READ_TMO, sc->sc_read);
553 if (rv) 347 if (rv)
554 return rv; 348 return rv;
555 349
556 bcnt = tpm_getburst(sc); 350 n = MIN(len, tpm_getburst(sc));
557 n = MIN(len, bcnt); 351 while (n > 0) {
558 
559 for (; n--; len--) { 
560 *p++ = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_DATA); 352 *p++ = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_DATA);
561 cnt++; 353 cnt++;
 354 len--;
 355 n--;
562 } 356 }
563 357
564 if ((flags & TPM_PARAM_SIZE) == 0 && cnt >= 6) 358 if ((flags & TPM_PARAM_SIZE) == 0 && cnt >= 6)
565 break; 359 break;
566 } 360 }
567 361
568 if (count) 362 if (count)
569 *count = cnt; 363 *count = cnt;
570 364
571 return 0; 365 return 0;
572} 366}
573 367
574int 368int
@@ -602,39 +396,38 @@ tpm_tis12_write(struct tpm_softc *sc, co @@ -602,39 +396,38 @@ tpm_tis12_write(struct tpm_softc *sc, co
602 cnt++; 396 cnt++;
603 397
604 if ((rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, sc))) { 398 if ((rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, sc))) {
605 return rv; 399 return rv;
606 } 400 }
607 if ((sc->sc_status & TPM_STS_DATA_EXPECT) != 0) { 401 if ((sc->sc_status & TPM_STS_DATA_EXPECT) != 0) {
608 return EIO; 402 return EIO;
609 } 403 }
610 404
611 return 0; 405 return 0;
612} 406}
613 407
614int 408int
615tpm_tis12_end(struct tpm_softc *sc, int flag, int err) 409tpm_tis12_end(struct tpm_softc *sc, int rw, int err)
616{ 410{
617 int rv = 0; 411 int rv = 0;
618 412
619 if (flag == UIO_READ) { 413 if (rw == UIO_READ) {
620 rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, sc->sc_read); 414 rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, sc->sc_read);
621 if (rv) 415 if (rv)
622 return rv; 416 return rv;
623 417
624 /* Still more data? */ 418 /* Still more data? */
625 sc->sc_status = tpm_status(sc); 419 sc->sc_status = tpm_status(sc);
626 if (!err && ((sc->sc_status & TPM_STS_DATA_AVAIL) == 420 if (!err && (sc->sc_status & TPM_STS_DATA_AVAIL)) {
627 TPM_STS_DATA_AVAIL)) { 
628 rv = EIO; 421 rv = EIO;
629 } 422 }
630 423
631 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS, 424 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS,
632 TPM_STS_CMD_READY); 425 TPM_STS_CMD_READY);
633 426
634 /* Release the 0th locality. */ 427 /* Release the 0th locality. */
635 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS, 428 bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS,
636 TPM_ACCESS_ACTIVE_LOCALITY); 429 TPM_ACCESS_ACTIVE_LOCALITY);
637 } else { 430 } else {
638 /* Hungry for more? */ 431 /* Hungry for more? */
639 sc->sc_status = tpm_status(sc); 432 sc->sc_status = tpm_status(sc);
640 if (!err && (sc->sc_status & TPM_STS_DATA_EXPECT)) { 433 if (!err && (sc->sc_status & TPM_STS_DATA_EXPECT)) {
@@ -658,155 +451,158 @@ static dev_type_ioctl(tpmioctl); @@ -658,155 +451,158 @@ static dev_type_ioctl(tpmioctl);
658 451
659const struct cdevsw tpm_cdevsw = { 452const struct cdevsw tpm_cdevsw = {
660 .d_open = tpmopen, 453 .d_open = tpmopen,
661 .d_close = tpmclose, 454 .d_close = tpmclose,
662 .d_read = tpmread, 455 .d_read = tpmread,
663 .d_write = tpmwrite, 456 .d_write = tpmwrite,
664 .d_ioctl = tpmioctl, 457 .d_ioctl = tpmioctl,
665 .d_stop = nostop, 458 .d_stop = nostop,
666 .d_tty = notty, 459 .d_tty = notty,
667 .d_poll = nopoll, 460 .d_poll = nopoll,
668 .d_mmap = nommap, 461 .d_mmap = nommap,
669 .d_kqfilter = nokqfilter, 462 .d_kqfilter = nokqfilter,
670 .d_discard = nodiscard, 463 .d_discard = nodiscard,
671 .d_flag = D_OTHER, 464 .d_flag = D_OTHER | D_MPSAFE,
672}; 465};
673 466
674#define TPMUNIT(a) minor(a) 
675 
676static int 467static int
677tpmopen(dev_t dev, int flag, int mode, struct lwp *l) 468tpmopen(dev_t dev, int flag, int mode, struct lwp *l)
678{ 469{
679 struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev)); 470 struct tpm_softc *sc = device_lookup_private(&tpm_cd, minor(dev));
 471 int ret = 0;
680 472
681 if (sc == NULL) 473 if (sc == NULL)
682 return ENXIO; 474 return ENXIO;
683 if (sc->sc_flags & TPM_OPEN) 
684 return EBUSY; 
685 475
686 sc->sc_flags |= TPM_OPEN; 476 mutex_enter(&sc->sc_lock);
 477 if (sc->sc_busy) {
 478 ret = EBUSY;
 479 } else {
 480 sc->sc_busy = true;
 481 }
 482 mutex_exit(&sc->sc_lock);
687 483
688 return 0; 484 return ret;
689} 485}
690 486
691static int 487static int
692tpmclose(dev_t dev, int flag, int mode, struct lwp *l) 488tpmclose(dev_t dev, int flag, int mode, struct lwp *l)
693{ 489{
694 struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev)); 490 struct tpm_softc *sc = device_lookup_private(&tpm_cd, minor(dev));
 491 int ret = 0;
695 492
696 if (sc == NULL) 493 if (sc == NULL)
697 return ENXIO; 494 return ENXIO;
698 if (!(sc->sc_flags & TPM_OPEN)) 
699 return EINVAL; 
700 495
701 sc->sc_flags &= ~TPM_OPEN; 496 mutex_enter(&sc->sc_lock);
 497 if (!sc->sc_busy) {
 498 ret = EINVAL;
 499 } else {
 500 sc->sc_busy = false;
 501 }
 502 mutex_exit(&sc->sc_lock);
702 503
703 return 0; 504 return ret;
704} 505}
705 506
706static int 507static int
707tpmread(dev_t dev, struct uio *uio, int flags) 508tpmread(dev_t dev, struct uio *uio, int flags)
708{ 509{
709 struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev)); 510 struct tpm_softc *sc = device_lookup_private(&tpm_cd, minor(dev));
710 uint8_t buf[TPM_BUFSIZ], *p; 511 uint8_t buf[TPM_BUFSIZ];
711 size_t cnt, len, n; 512 size_t cnt, len, n;
712 int rv, s; 513 int rv;
713 514
714 if (sc == NULL) 515 if (sc == NULL)
715 return ENXIO; 516 return ENXIO;
716 517
717 s = spltty(); 
718 if ((rv = (*sc->sc_start)(sc, UIO_READ))) 518 if ((rv = (*sc->sc_start)(sc, UIO_READ)))
719 goto out; 519 goto out;
720 520
 521 /* Get the header. */
721 if ((rv = (*sc->sc_read)(sc, buf, TPM_HDRSIZE, &cnt, 0))) { 522 if ((rv = (*sc->sc_read)(sc, buf, TPM_HDRSIZE, &cnt, 0))) {
722 (*sc->sc_end)(sc, UIO_READ, rv); 523 (*sc->sc_end)(sc, UIO_READ, rv);
723 goto out; 524 goto out;
724 } 525 }
725 
726 len = (buf[2] << 24) | (buf[3] << 16) | (buf[4] << 8) | buf[5]; 526 len = (buf[2] << 24) | (buf[3] << 16) | (buf[4] << 8) | buf[5];
727 if (len > uio->uio_resid) { 527 if (len > uio->uio_resid || len < cnt) {
728 rv = EIO; 528 rv = EIO;
729 (*sc->sc_end)(sc, UIO_READ, rv); 529 (*sc->sc_end)(sc, UIO_READ, rv);
730 goto out; 530 goto out;
731 } 531 }
732 532
733 /* Copy out header. */ 533 /* Copy out the header. */
734 if ((rv = uiomove(buf, cnt, uio))) { 534 if ((rv = uiomove(buf, cnt, uio))) {
735 (*sc->sc_end)(sc, UIO_READ, rv); 535 (*sc->sc_end)(sc, UIO_READ, rv);
736 goto out; 536 goto out;
737 } 537 }
738 538
739 /* Get remaining part of the answer (if anything is left). */ 539 /* Process the rest. */
740 for (len -= cnt, p = buf, n = sizeof(buf); len > 0; p = buf, len -= n, 540 len -= cnt;
741 n = sizeof(buf)) { 541 while (len > 0) {
742 n = MIN(n, len); 542 n = MIN(sizeof(buf), len);
743 if ((rv = (*sc->sc_read)(sc, p, n, NULL, TPM_PARAM_SIZE))) { 543 if ((rv = (*sc->sc_read)(sc, buf, n, NULL, TPM_PARAM_SIZE))) {
744 (*sc->sc_end)(sc, UIO_READ, rv); 544 (*sc->sc_end)(sc, UIO_READ, rv);
745 goto out; 545 goto out;
746 } 546 }
747 p += n; 547 if ((rv = uiomove(buf, n, uio))) {
748 if ((rv = uiomove(buf, p - buf, uio))) { 
749 (*sc->sc_end)(sc, UIO_READ, rv); 548 (*sc->sc_end)(sc, UIO_READ, rv);
750 goto out; 549 goto out;
751 } 550 }
 551 len -= n;
752 } 552 }
753 553
754 rv = (*sc->sc_end)(sc, UIO_READ, rv); 554 rv = (*sc->sc_end)(sc, UIO_READ, rv);
755out: 555out:
756 splx(s); 
757 return rv; 556 return rv;
758} 557}
759 558
760static int 559static int
761tpmwrite(dev_t dev, struct uio *uio, int flags) 560tpmwrite(dev_t dev, struct uio *uio, int flags)
762{ 561{
763 struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev)); 562 struct tpm_softc *sc = device_lookup_private(&tpm_cd, minor(dev));
764 uint8_t buf[TPM_BUFSIZ]; 563 uint8_t buf[TPM_BUFSIZ];
765 int n, rv, s; 564 int n, rv;
766 565
767 if (sc == NULL) 566 if (sc == NULL)
768 return ENXIO; 567 return ENXIO;
769 568
770 s = spltty(); 
771 
772 n = MIN(sizeof(buf), uio->uio_resid); 569 n = MIN(sizeof(buf), uio->uio_resid);
773 if ((rv = uiomove(buf, n, uio))) { 570 if ((rv = uiomove(buf, n, uio))) {
774 goto out; 571 goto out;
775 } 572 }
776 if ((rv = (*sc->sc_start)(sc, UIO_WRITE))) { 573 if ((rv = (*sc->sc_start)(sc, UIO_WRITE))) {
777 goto out; 574 goto out;
778 } 575 }
779 if ((rv = (*sc->sc_write)(sc, buf, n))) { 576 if ((rv = (*sc->sc_write)(sc, buf, n))) {
780 goto out; 577 goto out;
781 } 578 }
782 579
783 rv = (*sc->sc_end)(sc, UIO_WRITE, rv); 580 rv = (*sc->sc_end)(sc, UIO_WRITE, rv);
784out: 581out:
785 splx(s); 
786 return rv; 582 return rv;
787} 583}
788 584
789static int 585static int
790tpmioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) 586tpmioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
791{ 587{
792 struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev)); 588 struct tpm_softc *sc = device_lookup_private(&tpm_cd, minor(dev));
793 struct tpm_ioc_getinfo *info; 589 struct tpm_ioc_getinfo *info;
794 590
795 if (sc == NULL) 591 if (sc == NULL)
796 return ENXIO; 592 return ENXIO;
797 593
798 switch (cmd) { 594 switch (cmd) {
799 case TPM_IOC_GETINFO: 595 case TPM_IOC_GETINFO:
800 info = addr; 596 info = addr;
801 info->api_version = TPM_API_VERSION; 597 info->api_version = TPM_API_VERSION;
802 info->tpm_version = sc->sc_ver; 598 info->tpm_version = sc->sc_ver;
803 info->device_id = sc->sc_devid; 599 info->device_id = sc->sc_devid;
804 info->device_rev = sc->sc_rev; 600 info->device_rev = sc->sc_rev;
805 info->device_caps = sc->sc_capabilities; 601 info->device_caps = sc->sc_caps;
806 return 0; 602 return 0;
807 default: 603 default:
808 break; 604 break;
809 } 605 }
810 606
811 return ENOTTY; 607 return ENOTTY;
812} 608}

cvs diff -r1.4 -r1.5 src/sys/dev/ic/tpmreg.h (expand / switch to unified diff)

--- src/sys/dev/ic/tpmreg.h 2019/06/22 12:57:41 1.4
+++ src/sys/dev/ic/tpmreg.h 2019/10/08 18:43:02 1.5
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: tpmreg.h,v 1.4 2019/06/22 12:57:41 maxv Exp $ */ 1/* $NetBSD: tpmreg.h,v 1.5 2019/10/08 18:43:02 maxv Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2019 The NetBSD Foundation, Inc. 4 * Copyright (c) 2019 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Maxime Villard. 8 * by Maxime Villard.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -68,23 +68,24 @@ @@ -68,23 +68,24 @@
68#define TPM_INTF_STS_VALID_INT __BIT(1) 68#define TPM_INTF_STS_VALID_INT __BIT(1)
69#define TPM_INTF_DATA_AVAIL_INT __BIT(0) 69#define TPM_INTF_DATA_AVAIL_INT __BIT(0)
70#define TPM_INTF_CAPABILITY_BITS \ 70#define TPM_INTF_CAPABILITY_BITS \
71 "\020\01IDRDY\02ISTSV\03ILOCH\04IHIGH\05ILOW\06IRISE\07IFALL\010IRDY\011BCST" 71 "\020\01IDRDY\02ISTSV\03ILOCH\04IHIGH\05ILOW\06IRISE\07IFALL\010IRDY\011BCST"
72 72
73#define TPM_STS 0x0018 /* 24bit register */ 73#define TPM_STS 0x0018 /* 24bit register */
74#define TPM_STS_BURST_COUNT __BITS(23,8) 74#define TPM_STS_BURST_COUNT __BITS(23,8)
75#define TPM_STS_STATUS_BITS __BITS(7,0) 75#define TPM_STS_STATUS_BITS __BITS(7,0)
76#define TPM_STS_VALID __BIT(7) 76#define TPM_STS_VALID __BIT(7)
77#define TPM_STS_CMD_READY __BIT(6) 77#define TPM_STS_CMD_READY __BIT(6)
78#define TPM_STS_GO __BIT(5) 78#define TPM_STS_GO __BIT(5)
79#define TPM_STS_DATA_AVAIL __BIT(4) 79#define TPM_STS_DATA_AVAIL __BIT(4)
80#define TPM_STS_DATA_EXPECT __BIT(3) 80#define TPM_STS_DATA_EXPECT __BIT(3)
 81#define TPM_STS_SELFTEST_DONE __BIT(2)
81#define TPM_STS_RESP_RETRY __BIT(1) 82#define TPM_STS_RESP_RETRY __BIT(1)
82 83
83#define TPM_DATA 0x0024 /* 32bit register */ 84#define TPM_DATA 0x0024 /* 32bit register */
84#define TPM_ID 0x0f00 /* 32bit register */ 85#define TPM_ID 0x0f00 /* 32bit register */
85#define TPM_REV 0x0f04 /* 8bit register */ 86#define TPM_REV 0x0f04 /* 8bit register */
86 87
87/* 88/*
88 * Five localities, 4K per locality. 89 * Five localities, 4K per locality.
89 */ 90 */
90#define TPM_SPACE_SIZE 0x5000 91#define TPM_SPACE_SIZE 0x5000

cvs diff -r1.4 -r1.5 src/sys/dev/ic/tpmvar.h (expand / switch to unified diff)

--- src/sys/dev/ic/tpmvar.h 2019/06/22 12:57:41 1.4
+++ src/sys/dev/ic/tpmvar.h 2019/10/08 18:43:02 1.5
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: tpmvar.h,v 1.4 2019/06/22 12:57:41 maxv Exp $ */ 1/* $NetBSD: tpmvar.h,v 1.5 2019/10/08 18:43:02 maxv Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2019 The NetBSD Foundation, Inc. 4 * Copyright (c) 2019 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Maxime Villard. 8 * by Maxime Villard.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -19,89 +19,64 @@ @@ -19,89 +19,64 @@
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 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 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 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 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 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 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#define TPM_API_VERSION 1 32#define TPM_API_VERSION 1
51 33
52enum tpm_version { 34enum tpm_version {
53 TPM_1_2, 35 TPM_1_2,
54 TPM_2_0 36 TPM_2_0
55}; 37};
56 38
57struct tpm_ioc_getinfo { 39struct tpm_ioc_getinfo {
58 uint32_t api_version; 40 uint32_t api_version;
59 
60 uint32_t tpm_version; 41 uint32_t tpm_version;
61 uint32_t device_id; 42 uint32_t device_id;
62 uint32_t device_rev; 43 uint32_t device_rev;
63 uint32_t device_caps; 44 uint32_t device_caps;
64}; 45};
65 46
66#define TPM_IOC_GETINFO _IOR ('N', 0, struct tpm_ioc_getinfo) 47#define TPM_IOC_GETINFO _IOR ('N', 0, struct tpm_ioc_getinfo)
67 48
68#ifdef _KERNEL 49#ifdef _KERNEL
69 50
70struct tpm_softc { 51struct tpm_softc {
71 device_t sc_dev; 52 device_t sc_dev;
72 enum tpm_version sc_ver; 53 enum tpm_version sc_ver;
73 void *sc_ih; 54 kmutex_t sc_lock;
 55 bool sc_busy;
74 56
75 int (*sc_init)(struct tpm_softc *, int); 57 int (*sc_init)(struct tpm_softc *);
76 int (*sc_start)(struct tpm_softc *, int); 58 int (*sc_start)(struct tpm_softc *, int);
77 int (*sc_read)(struct tpm_softc *, void *, size_t, size_t *, int); 59 int (*sc_read)(struct tpm_softc *, void *, size_t, size_t *, int);
78 int (*sc_write)(struct tpm_softc *, const void *, size_t); 60 int (*sc_write)(struct tpm_softc *, const void *, size_t);
79 int (*sc_end)(struct tpm_softc *, int, int); 61 int (*sc_end)(struct tpm_softc *, int, int);
80 62
81 bus_space_tag_t sc_bt, sc_batm; 63 bus_space_tag_t sc_bt;
82 bus_space_handle_t sc_bh, sc_bahm; 64 bus_space_handle_t sc_bh;
83 65
84 uint32_t sc_devid; 66 uint32_t sc_devid;
85 uint32_t sc_rev; 67 uint32_t sc_rev;
86 uint32_t sc_status; 68 uint32_t sc_status;
87 uint32_t sc_capabilities; 69 uint32_t sc_caps;
88 
89 int sc_flags; 
90#define TPM_OPEN 0x0001 
91 
92 int sc_vector; 
93}; 70};
94 71
95int tpm_intr(void *); 
96 
97bool tpm12_suspend(device_t, const pmf_qual_t *); 72bool tpm12_suspend(device_t, const pmf_qual_t *);
98bool tpm12_resume(device_t, const pmf_qual_t *); 73bool tpm12_resume(device_t, const pmf_qual_t *);
99 74
100int tpm_tis12_probe(bus_space_tag_t, bus_space_handle_t); 75int tpm_tis12_probe(bus_space_tag_t, bus_space_handle_t);
101int tpm_tis12_init(struct tpm_softc *, int); 76int tpm_tis12_init(struct tpm_softc *);
102int tpm_tis12_start(struct tpm_softc *, int); 77int tpm_tis12_start(struct tpm_softc *, int);
103int tpm_tis12_read(struct tpm_softc *, void *, size_t, size_t *, int); 78int tpm_tis12_read(struct tpm_softc *, void *, size_t, size_t *, int);
104int tpm_tis12_write(struct tpm_softc *, const void *, size_t); 79int tpm_tis12_write(struct tpm_softc *, const void *, size_t);
105int tpm_tis12_end(struct tpm_softc *, int, int); 80int tpm_tis12_end(struct tpm_softc *, int, int);
106 81
107#endif 82#endif

cvs diff -r1.4 -r1.5 src/sys/dev/isa/tpm_isa.c (expand / switch to unified diff)

--- src/sys/dev/isa/tpm_isa.c 2019/06/22 12:57:41 1.4
+++ src/sys/dev/isa/tpm_isa.c 2019/10/08 18:43:03 1.5
@@ -1,125 +1,138 @@ @@ -1,125 +1,138 @@
1/* $NetBSD: tpm_isa.c,v 1.4 2019/06/22 12:57:41 maxv Exp $ */ 1/* $NetBSD: tpm_isa.c,v 1.5 2019/10/08 18:43:03 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 */
2 31
3/* 32/*
4 * Copyright (c) 2008, 2009 Michael Shalayeff 33 * Copyright (c) 2008, 2009 Michael Shalayeff
5 * Copyright (c) 2009, 2010 Hans-Jörg Höxer 34 * Copyright (c) 2009, 2010 Hans-Joerg Hoexer
6 * All rights reserved. 35 * All rights reserved.
7 * 36 *
8 * Permission to use, copy, modify, and distribute this software for any 37 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above 38 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies. 39 * copyright notice and this permission notice appear in all copies.
11 * 40 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 41 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 42 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 43 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 44 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN 45 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
17 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 46 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
18 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 47 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 */ 48 */
20 49
21#include <sys/cdefs.h> 50#include <sys/cdefs.h>
22__KERNEL_RCSID(0, "$NetBSD: tpm_isa.c,v 1.4 2019/06/22 12:57:41 maxv Exp $"); 51__KERNEL_RCSID(0, "$NetBSD: tpm_isa.c,v 1.5 2019/10/08 18:43:03 maxv Exp $");
23 52
24#include <sys/param.h> 53#include <sys/param.h>
25#include <sys/systm.h> 54#include <sys/systm.h>
26#include <sys/kernel.h> 
27#include <sys/malloc.h> 
28#include <sys/proc.h> 
29#include <sys/device.h> 55#include <sys/device.h>
30#include <sys/bus.h> 56#include <sys/bus.h>
31#include <sys/pmf.h> 57#include <sys/pmf.h>
32 58
33#include <dev/ic/tpmreg.h> 59#include <dev/ic/tpmreg.h>
34#include <dev/ic/tpmvar.h> 60#include <dev/ic/tpmvar.h>
35 61
36#include <dev/isa/isareg.h> 62#include <dev/isa/isareg.h>
37#include <dev/isa/isavar.h> 63#include <dev/isa/isavar.h>
38 64
 65#include "ioconf.h"
 66
39static int tpm_isa_match(device_t, cfdata_t, void *); 67static int tpm_isa_match(device_t, cfdata_t, void *);
40static void tpm_isa_attach(device_t, device_t, void *); 68static void tpm_isa_attach(device_t, device_t, void *);
41 69
42CFATTACH_DECL_NEW(tpm_isa, sizeof(struct tpm_softc), 70CFATTACH_DECL_NEW(tpm_isa, sizeof(struct tpm_softc), tpm_isa_match,
43 tpm_isa_match, tpm_isa_attach, NULL, NULL); 71 tpm_isa_attach, NULL, NULL);
44 
45extern struct cfdriver tpm_cd; 
46 72
47static int 73static int
48tpm_isa_match(device_t parent, cfdata_t match, void *aux) 74tpm_isa_match(device_t parent, cfdata_t match, void *aux)
49{ 75{
50 struct isa_attach_args *ia = aux; 76 struct isa_attach_args *ia = aux;
51 bus_space_tag_t bt = ia->ia_memt; 77 bus_space_tag_t bt = ia->ia_memt;
52 bus_space_handle_t bh; 78 bus_space_handle_t bh;
53 int rv; 79 int rv;
54 80
55 /* There can be only one. */ 81 /* There can be only one. */
56 if (tpm_cd.cd_devs && tpm_cd.cd_devs[0]) 82 if (tpm_cd.cd_devs && tpm_cd.cd_devs[0])
57 return 0; 83 return 0;
58 84
59 if (ia->ia_iomem[0].ir_addr == ISA_UNKNOWN_IOMEM) 85 if (ia->ia_iomem[0].ir_addr == ISA_UNKNOWN_IOMEM)
60 return 0; 86 return 0;
61 87
62 /* XXX: integer locator sign extension */ 88 /* XXX: integer locator sign extension */
63 if (bus_space_map(bt, (unsigned int)ia->ia_iomem[0].ir_addr, TPM_SPACE_SIZE, 89 if (bus_space_map(bt, (unsigned int)ia->ia_iomem[0].ir_addr,
64 0, &bh)) 90 TPM_SPACE_SIZE, 0, &bh))
65 return 0; 91 return 0;
66 92
67 if ((rv = tpm_tis12_probe(bt, bh))) { 93 if ((rv = tpm_tis12_probe(bt, bh))) {
68 ia->ia_nio = 0; 94 ia->ia_nio = 0;
69 ia->ia_io[0].ir_size = 0; 95 ia->ia_io[0].ir_size = 0;
70 ia->ia_iomem[0].ir_size = TPM_SPACE_SIZE; 96 ia->ia_iomem[0].ir_size = TPM_SPACE_SIZE;
71 } 97 }
72 ia->ia_ndrq = 0; 98 ia->ia_ndrq = 0;
73 99
74 bus_space_unmap(bt, bh, TPM_SPACE_SIZE); 100 bus_space_unmap(bt, bh, TPM_SPACE_SIZE);
75 return rv; 101 return rv;
76} 102}
77 103
78static void 104static void
79tpm_isa_attach(device_t parent, device_t self, void *aux) 105tpm_isa_attach(device_t parent, device_t self, void *aux)
80{ 106{
81 struct tpm_softc *sc = device_private(self); 107 struct tpm_softc *sc = device_private(self);
82 struct isa_attach_args *ia = aux; 108 struct isa_attach_args *ia = aux;
83 bus_addr_t iobase; 109 bus_addr_t base;
84 bus_size_t size; 110 bus_size_t size;
85 int rv; 
86 111
87 sc->sc_dev = self; 112 sc->sc_dev = self;
88 sc->sc_ver = TPM_1_2; 113 sc->sc_ver = TPM_1_2;
89 114 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
90 sc->sc_bt = ia->ia_memt; 115 sc->sc_busy = false;
91 iobase = (unsigned int)ia->ia_iomem[0].ir_addr; 
92 size = TPM_SPACE_SIZE; 
93 sc->sc_init = tpm_tis12_init; 116 sc->sc_init = tpm_tis12_init;
94 sc->sc_start = tpm_tis12_start; 117 sc->sc_start = tpm_tis12_start;
95 sc->sc_read = tpm_tis12_read; 118 sc->sc_read = tpm_tis12_read;
96 sc->sc_write = tpm_tis12_write; 119 sc->sc_write = tpm_tis12_write;
97 sc->sc_end = tpm_tis12_end; 120 sc->sc_end = tpm_tis12_end;
 121 sc->sc_bt = ia->ia_memt;
98 122
99 if (bus_space_map(sc->sc_bt, iobase, size, 0, &sc->sc_bh)) { 123 base = (unsigned int)ia->ia_iomem[0].ir_addr;
 124 size = TPM_SPACE_SIZE;
 125
 126 if (bus_space_map(sc->sc_bt, base, size, 0, &sc->sc_bh)) {
100 aprint_error_dev(sc->sc_dev, "cannot map registers\n"); 127 aprint_error_dev(sc->sc_dev, "cannot map registers\n");
101 return; 128 return;
102 } 129 }
103 130
104 if ((rv = (*sc->sc_init)(sc, ia->ia_irq[0].ir_irq)) != 0) { 131 if ((*sc->sc_init)(sc) != 0) {
105 bus_space_unmap(sc->sc_bt, sc->sc_bh, size); 132 bus_space_unmap(sc->sc_bt, sc->sc_bh, size);
106 return; 133 return;
107 } 134 }
108 135
109 /* 
110 * Only setup interrupt handler when we have a vector and the 
111 * chip is TIS 1.2 compliant. 
112 */ 
113 if (sc->sc_init == tpm_tis12_init && 
114 ia->ia_irq[0].ir_irq != ISA_UNKNOWN_IRQ && 
115 (sc->sc_ih = isa_intr_establish_xname(ia->ia_ic, 
116 ia->ia_irq[0].ir_irq, IST_EDGE, IPL_TTY, tpm_intr, sc, 
117 device_xname(sc->sc_dev))) == NULL) { 
118 bus_space_unmap(sc->sc_bt, sc->sc_bh, TPM_SPACE_SIZE); 
119 aprint_error_dev(sc->sc_dev, "cannot establish interrupt\n"); 
120 return; 
121 } 
122 
123 if (!pmf_device_register(sc->sc_dev, tpm12_suspend, tpm12_resume)) 136 if (!pmf_device_register(sc->sc_dev, tpm12_suspend, tpm12_resume))
124 aprint_error_dev(sc->sc_dev, "cannot set power mgmt handler\n"); 137 aprint_error_dev(sc->sc_dev, "couldn't establish power handler\n");
125} 138}