Home | History | Annotate | Line # | Download | only in isa
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