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