1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2004 IBM Corporation 4 * 5 * Authors: 6 * Leendert van Doorn <leendert@watson.ibm.com> 7 * Dave Safford <safford@watson.ibm.com> 8 * Reiner Sailer <sailer@watson.ibm.com> 9 * Kylene Hall <kjhall@us.ibm.com> 10 * 11 * Maintained by: <tpmdd-devel@lists.sourceforge.net> 12 * 13 * Device driver for TCG/TCPA TPM (trusted platform module). 14 * Specifications at www.trustedcomputinggroup.org 15 */ 16 17 #include "tpm.h" 18 19 struct tpm_atmel_priv { 20 int region_size; 21 int have_region; 22 unsigned long base; 23 void __iomem *iobase; 24 }; 25 26 #define atmel_getb(chip, offset) inb(atmel_get_priv(chip)->base + (offset)) 27 #define atmel_putb(val, chip, offset) \ 28 outb(val, atmel_get_priv(chip)->base + (offset)) 29 #define atmel_request_region request_region 30 #define atmel_release_region release_region 31 /* Atmel definitions */ 32 enum tpm_atmel_addr { 33 TPM_ATMEL_BASE_ADDR_LO = 0x08, 34 TPM_ATMEL_BASE_ADDR_HI = 0x09 35 }; 36 37 static inline int tpm_read_index(int base, int index) 38 { 39 outb(index, base); 40 return inb(base + 1) & 0xFF; 41 } 42 43 /* Verify this is a 1.1 Atmel TPM */ 44 static int atmel_verify_tpm11(void) 45 { 46 /* verify that it is an Atmel part */ 47 if (tpm_read_index(TPM_ADDR, 4) != 'A' || 48 tpm_read_index(TPM_ADDR, 5) != 'T' || 49 tpm_read_index(TPM_ADDR, 6) != 'M' || 50 tpm_read_index(TPM_ADDR, 7) != 'L') 51 return 1; 52 53 /* query chip for its version number */ 54 if (tpm_read_index(TPM_ADDR, 0x00) != 1 || 55 tpm_read_index(TPM_ADDR, 0x01) != 1) 56 return 1; 57 58 /* This is an atmel supported part */ 59 return 0; 60 } 61 62 /* Determine where to talk to device */ 63 static void __iomem *atmel_get_base_addr(unsigned long *base, int *region_size) 64 { 65 int lo, hi; 66 67 if (atmel_verify_tpm11() != 0) 68 return NULL; 69 70 lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO); 71 hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI); 72 73 *base = (hi << 8) | lo; 74 *region_size = 2; 75 76 return ioport_map(*base, *region_size); 77 } 78 79 /* write status bits */ 80 enum tpm_atmel_write_status { 81 ATML_STATUS_ABORT = 0x01, 82 ATML_STATUS_LASTBYTE = 0x04 83 }; 84 /* read status bits */ 85 enum tpm_atmel_read_status { 86 ATML_STATUS_BUSY = 0x01, 87 ATML_STATUS_DATA_AVAIL = 0x02, 88 ATML_STATUS_REWRITE = 0x04, 89 ATML_STATUS_READY = 0x08 90 }; 91 92 static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) 93 { 94 struct tpm_atmel_priv *priv = dev_get_drvdata(&chip->dev); 95 u8 status, *hdr = buf; 96 u32 size; 97 int i; 98 __be32 *native_size; 99 100 /* start reading header */ 101 if (count < 6) 102 return -EIO; 103 104 for (i = 0; i < 6; i++) { 105 status = ioread8(priv->iobase + 1); 106 if ((status & ATML_STATUS_DATA_AVAIL) == 0) { 107 dev_err(&chip->dev, "error reading header\n"); 108 return -EIO; 109 } 110 *buf++ = ioread8(priv->iobase); 111 } 112 113 /* size of the data received */ 114 native_size = (__force __be32 *) (hdr + 2); 115 size = be32_to_cpu(*native_size); 116 117 if (count < size) { 118 dev_err(&chip->dev, 119 "Recv size(%d) less than available space\n", size); 120 for (; i < size; i++) { /* clear the waiting data anyway */ 121 status = ioread8(priv->iobase + 1); 122 if ((status & ATML_STATUS_DATA_AVAIL) == 0) { 123 dev_err(&chip->dev, "error reading data\n"); 124 return -EIO; 125 } 126 } 127 return -EIO; 128 } 129 130 /* read all the data available */ 131 for (; i < size; i++) { 132 status = ioread8(priv->iobase + 1); 133 if ((status & ATML_STATUS_DATA_AVAIL) == 0) { 134 dev_err(&chip->dev, "error reading data\n"); 135 return -EIO; 136 } 137 *buf++ = ioread8(priv->iobase); 138 } 139 140 /* make sure data available is gone */ 141 status = ioread8(priv->iobase + 1); 142 143 if (status & ATML_STATUS_DATA_AVAIL) { 144 dev_err(&chip->dev, "data available is stuck\n"); 145 return -EIO; 146 } 147 148 return size; 149 } 150 151 static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz, 152 size_t count) 153 { 154 struct tpm_atmel_priv *priv = dev_get_drvdata(&chip->dev); 155 int i; 156 157 dev_dbg(&chip->dev, "tpm_atml_send:\n"); 158 for (i = 0; i < count; i++) { 159 dev_dbg(&chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); 160 iowrite8(buf[i], priv->iobase); 161 } 162 163 return 0; 164 } 165 166 static void tpm_atml_cancel(struct tpm_chip *chip) 167 { 168 struct tpm_atmel_priv *priv = dev_get_drvdata(&chip->dev); 169 170 iowrite8(ATML_STATUS_ABORT, priv->iobase + 1); 171 } 172 173 static u8 tpm_atml_status(struct tpm_chip *chip) 174 { 175 struct tpm_atmel_priv *priv = dev_get_drvdata(&chip->dev); 176 177 return ioread8(priv->iobase + 1); 178 } 179 180 static bool tpm_atml_req_canceled(struct tpm_chip *chip, u8 status) 181 { 182 return (status == ATML_STATUS_READY); 183 } 184 185 static const struct tpm_class_ops tpm_atmel = { 186 .recv = tpm_atml_recv, 187 .send = tpm_atml_send, 188 .cancel = tpm_atml_cancel, 189 .status = tpm_atml_status, 190 .req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL, 191 .req_complete_val = ATML_STATUS_DATA_AVAIL, 192 .req_canceled = tpm_atml_req_canceled, 193 }; 194 195 static struct platform_device *pdev; 196 197 static void atml_plat_remove(void) 198 { 199 struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); 200 struct tpm_atmel_priv *priv = dev_get_drvdata(&chip->dev); 201 202 tpm_chip_unregister(chip); 203 if (priv->have_region) 204 atmel_release_region(priv->base, priv->region_size); 205 platform_device_unregister(pdev); 206 } 207 208 static SIMPLE_DEV_PM_OPS(tpm_atml_pm, tpm_pm_suspend, tpm_pm_resume); 209 210 static struct platform_driver atml_drv = { 211 .driver = { 212 .name = "tpm_atmel", 213 .pm = &tpm_atml_pm, 214 }, 215 }; 216 217 static int __init init_atmel(void) 218 { 219 int rc = 0; 220 void __iomem *iobase = NULL; 221 int have_region, region_size; 222 unsigned long base; 223 struct tpm_chip *chip; 224 struct tpm_atmel_priv *priv; 225 226 rc = platform_driver_register(&atml_drv); 227 if (rc) 228 return rc; 229 230 if ((iobase = atmel_get_base_addr(&base, ®ion_size)) == NULL) { 231 rc = -ENODEV; 232 goto err_unreg_drv; 233 } 234 235 have_region = 236 (atmel_request_region 237 (base, region_size, "tpm_atmel0") == NULL) ? 0 : 1; 238 239 pdev = platform_device_register_simple("tpm_atmel", -1, NULL, 0); 240 if (IS_ERR(pdev)) { 241 rc = PTR_ERR(pdev); 242 goto err_rel_reg; 243 } 244 245 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 246 if (!priv) { 247 rc = -ENOMEM; 248 goto err_unreg_dev; 249 } 250 251 priv->iobase = iobase; 252 priv->base = base; 253 priv->have_region = have_region; 254 priv->region_size = region_size; 255 256 chip = tpmm_chip_alloc(&pdev->dev, &tpm_atmel); 257 if (IS_ERR(chip)) { 258 rc = PTR_ERR(chip); 259 goto err_unreg_dev; 260 } 261 262 dev_set_drvdata(&chip->dev, priv); 263 264 rc = tpm_chip_register(chip); 265 if (rc) 266 goto err_unreg_dev; 267 268 return 0; 269 270 err_unreg_dev: 271 platform_device_unregister(pdev); 272 err_rel_reg: 273 if (have_region) 274 atmel_release_region(base, 275 region_size); 276 err_unreg_drv: 277 platform_driver_unregister(&atml_drv); 278 return rc; 279 } 280 281 static void __exit cleanup_atmel(void) 282 { 283 platform_driver_unregister(&atml_drv); 284 atml_plat_remove(); 285 } 286 287 module_init(init_atmel); 288 module_exit(cleanup_atmel); 289 290 MODULE_AUTHOR("Leendert van Doorn <leendert@watson.ibm.com>"); 291 MODULE_DESCRIPTION("TPM Driver"); 292 MODULE_VERSION("2.0"); 293 MODULE_LICENSE("GPL"); 294