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