linux/drivers/char/tpm/tpm_atmel.h
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2005 IBM Corporation
   3 *
   4 * Authors:
   5 * Kylene Hall <kjhall@us.ibm.com>
   6 *
   7 * Maintained by: <tpmdd-devel@lists.sourceforge.net>
   8 *
   9 * Device driver for TCG/TCPA TPM (trusted platform module).
  10 * Specifications at www.trustedcomputinggroup.org
  11 *
  12 * This program is free software; you can redistribute it and/or
  13 * modify it under the terms of the GNU General Public License as
  14 * published by the Free Software Foundation, version 2 of the
  15 * License.
  16 *
  17 * These difference are required on power because the device must be
  18 * discovered through the device tree and iomap must be used to get
  19 * around the need for holes in the io_page_mask.  This does not happen
  20 * automatically because the tpm is not a normal pci device and lives
  21 * under the root node.
  22 *
  23 */
  24
  25struct tpm_atmel_priv {
  26        int region_size;
  27        int have_region;
  28        unsigned long base;
  29        void __iomem *iobase;
  30};
  31
  32#ifdef CONFIG_PPC64
  33
  34#include <asm/prom.h>
  35
  36#define atmel_getb(priv, offset) readb(priv->iobase + offset)
  37#define atmel_putb(val, priv, offset) writeb(val, priv->iobase + offset)
  38#define atmel_request_region request_mem_region
  39#define atmel_release_region release_mem_region
  40
  41static inline void atmel_put_base_addr(void __iomem *iobase)
  42{
  43        iounmap(iobase);
  44}
  45
  46static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
  47{
  48        struct device_node *dn;
  49        unsigned long address, size;
  50        const unsigned int *reg;
  51        int reglen;
  52        int naddrc;
  53        int nsizec;
  54
  55        dn = of_find_node_by_name(NULL, "tpm");
  56
  57        if (!dn)
  58                return NULL;
  59
  60        if (!of_device_is_compatible(dn, "AT97SC3201")) {
  61                of_node_put(dn);
  62                return NULL;
  63        }
  64
  65        reg = of_get_property(dn, "reg", &reglen);
  66        naddrc = of_n_addr_cells(dn);
  67        nsizec = of_n_size_cells(dn);
  68
  69        of_node_put(dn);
  70
  71
  72        if (naddrc == 2)
  73                address = ((unsigned long) reg[0] << 32) | reg[1];
  74        else
  75                address = reg[0];
  76
  77        if (nsizec == 2)
  78                size =
  79                    ((unsigned long) reg[naddrc] << 32) | reg[naddrc + 1];
  80        else
  81                size = reg[naddrc];
  82
  83        *base = address;
  84        *region_size = size;
  85        return ioremap(*base, *region_size);
  86}
  87#else
  88#define atmel_getb(chip, offset) inb(atmel_get_priv(chip)->base + offset)
  89#define atmel_putb(val, chip, offset) \
  90        outb(val, atmel_get_priv(chip)->base + offset)
  91#define atmel_request_region request_region
  92#define atmel_release_region release_region
  93/* Atmel definitions */
  94enum tpm_atmel_addr {
  95        TPM_ATMEL_BASE_ADDR_LO = 0x08,
  96        TPM_ATMEL_BASE_ADDR_HI = 0x09
  97};
  98
  99static inline int tpm_read_index(int base, int index)
 100{
 101        outb(index, base);
 102        return inb(base+1) & 0xFF;
 103}
 104
 105/* Verify this is a 1.1 Atmel TPM */
 106static int atmel_verify_tpm11(void)
 107{
 108
 109        /* verify that it is an Atmel part */
 110        if (tpm_read_index(TPM_ADDR, 4) != 'A' ||
 111            tpm_read_index(TPM_ADDR, 5) != 'T' ||
 112            tpm_read_index(TPM_ADDR, 6) != 'M' ||
 113            tpm_read_index(TPM_ADDR, 7) != 'L')
 114                return 1;
 115
 116        /* query chip for its version number */
 117        if (tpm_read_index(TPM_ADDR, 0x00) != 1 ||
 118            tpm_read_index(TPM_ADDR, 0x01) != 1)
 119                return 1;
 120
 121        /* This is an atmel supported part */
 122        return 0;
 123}
 124
 125static inline void atmel_put_base_addr(void __iomem *iobase)
 126{
 127}
 128
 129/* Determine where to talk to device */
 130static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
 131{
 132        int lo, hi;
 133
 134        if (atmel_verify_tpm11() != 0)
 135                return NULL;
 136
 137        lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
 138        hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
 139
 140        *base = (hi << 8) | lo;
 141        *region_size = 2;
 142
 143        return ioport_map(*base, *region_size);
 144}
 145#endif
 146