root/drivers/char/tpm/tpm_tis.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. to_tpm_tis_tcg_phy
  2. has_hid
  3. is_itpm
  4. is_itpm
  5. check_acpi_tpm2
  6. check_acpi_tpm2
  7. tpm_tcg_read_bytes
  8. tpm_tcg_write_bytes
  9. tpm_tcg_read16
  10. tpm_tcg_read32
  11. tpm_tcg_write32
  12. tpm_tis_init
  13. tpm_tis_pnp_init
  14. tpm_tis_pnp_remove
  15. tpm_tis_plat_probe
  16. tpm_tis_plat_remove
  17. tpm_tis_force_device
  18. init_tis
  19. cleanup_tis

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) 2005, 2006 IBM Corporation
   4  * Copyright (C) 2014, 2015 Intel Corporation
   5  *
   6  * Authors:
   7  * Leendert van Doorn <leendert@watson.ibm.com>
   8  * Kylene Hall <kjhall@us.ibm.com>
   9  *
  10  * Maintained by: <tpmdd-devel@lists.sourceforge.net>
  11  *
  12  * Device driver for TCG/TCPA TPM (trusted platform module).
  13  * Specifications at www.trustedcomputinggroup.org
  14  *
  15  * This device driver implements the TPM interface as defined in
  16  * the TCG TPM Interface Spec version 1.2, revision 1.0.
  17  */
  18 #include <linux/init.h>
  19 #include <linux/module.h>
  20 #include <linux/moduleparam.h>
  21 #include <linux/pnp.h>
  22 #include <linux/slab.h>
  23 #include <linux/interrupt.h>
  24 #include <linux/wait.h>
  25 #include <linux/acpi.h>
  26 #include <linux/freezer.h>
  27 #include <linux/of.h>
  28 #include <linux/of_device.h>
  29 #include <linux/kernel.h>
  30 #include "tpm.h"
  31 #include "tpm_tis_core.h"
  32 
  33 struct tpm_info {
  34         struct resource res;
  35         /* irq > 0 means: use irq $irq;
  36          * irq = 0 means: autoprobe for an irq;
  37          * irq = -1 means: no irq support
  38          */
  39         int irq;
  40 };
  41 
  42 struct tpm_tis_tcg_phy {
  43         struct tpm_tis_data priv;
  44         void __iomem *iobase;
  45 };
  46 
  47 static inline struct tpm_tis_tcg_phy *to_tpm_tis_tcg_phy(struct tpm_tis_data *data)
  48 {
  49         return container_of(data, struct tpm_tis_tcg_phy, priv);
  50 }
  51 
  52 static bool interrupts = true;
  53 module_param(interrupts, bool, 0444);
  54 MODULE_PARM_DESC(interrupts, "Enable interrupts");
  55 
  56 static bool itpm;
  57 module_param(itpm, bool, 0444);
  58 MODULE_PARM_DESC(itpm, "Force iTPM workarounds (found on some Lenovo laptops)");
  59 
  60 static bool force;
  61 #ifdef CONFIG_X86
  62 module_param(force, bool, 0444);
  63 MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry");
  64 #endif
  65 
  66 #if defined(CONFIG_PNP) && defined(CONFIG_ACPI)
  67 static int has_hid(struct acpi_device *dev, const char *hid)
  68 {
  69         struct acpi_hardware_id *id;
  70 
  71         list_for_each_entry(id, &dev->pnp.ids, list)
  72                 if (!strcmp(hid, id->id))
  73                         return 1;
  74 
  75         return 0;
  76 }
  77 
  78 static inline int is_itpm(struct acpi_device *dev)
  79 {
  80         if (!dev)
  81                 return 0;
  82         return has_hid(dev, "INTC0102");
  83 }
  84 #else
  85 static inline int is_itpm(struct acpi_device *dev)
  86 {
  87         return 0;
  88 }
  89 #endif
  90 
  91 #if defined(CONFIG_ACPI)
  92 #define DEVICE_IS_TPM2 1
  93 
  94 static const struct acpi_device_id tpm_acpi_tbl[] = {
  95         {"MSFT0101", DEVICE_IS_TPM2},
  96         {},
  97 };
  98 MODULE_DEVICE_TABLE(acpi, tpm_acpi_tbl);
  99 
 100 static int check_acpi_tpm2(struct device *dev)
 101 {
 102         const struct acpi_device_id *aid = acpi_match_device(tpm_acpi_tbl, dev);
 103         struct acpi_table_tpm2 *tbl;
 104         acpi_status st;
 105 
 106         if (!aid || aid->driver_data != DEVICE_IS_TPM2)
 107                 return 0;
 108 
 109         /* If the ACPI TPM2 signature is matched then a global ACPI_SIG_TPM2
 110          * table is mandatory
 111          */
 112         st =
 113             acpi_get_table(ACPI_SIG_TPM2, 1, (struct acpi_table_header **)&tbl);
 114         if (ACPI_FAILURE(st) || tbl->header.length < sizeof(*tbl)) {
 115                 dev_err(dev, FW_BUG "failed to get TPM2 ACPI table\n");
 116                 return -EINVAL;
 117         }
 118 
 119         /* The tpm2_crb driver handles this device */
 120         if (tbl->start_method != ACPI_TPM2_MEMORY_MAPPED)
 121                 return -ENODEV;
 122 
 123         return 0;
 124 }
 125 #else
 126 static int check_acpi_tpm2(struct device *dev)
 127 {
 128         return 0;
 129 }
 130 #endif
 131 
 132 static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
 133                               u8 *result)
 134 {
 135         struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 136 
 137         while (len--)
 138                 *result++ = ioread8(phy->iobase + addr);
 139 
 140         return 0;
 141 }
 142 
 143 static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
 144                                const u8 *value)
 145 {
 146         struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 147 
 148         while (len--)
 149                 iowrite8(*value++, phy->iobase + addr);
 150 
 151         return 0;
 152 }
 153 
 154 static int tpm_tcg_read16(struct tpm_tis_data *data, u32 addr, u16 *result)
 155 {
 156         struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 157 
 158         *result = ioread16(phy->iobase + addr);
 159 
 160         return 0;
 161 }
 162 
 163 static int tpm_tcg_read32(struct tpm_tis_data *data, u32 addr, u32 *result)
 164 {
 165         struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 166 
 167         *result = ioread32(phy->iobase + addr);
 168 
 169         return 0;
 170 }
 171 
 172 static int tpm_tcg_write32(struct tpm_tis_data *data, u32 addr, u32 value)
 173 {
 174         struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 175 
 176         iowrite32(value, phy->iobase + addr);
 177 
 178         return 0;
 179 }
 180 
 181 static const struct tpm_tis_phy_ops tpm_tcg = {
 182         .read_bytes = tpm_tcg_read_bytes,
 183         .write_bytes = tpm_tcg_write_bytes,
 184         .read16 = tpm_tcg_read16,
 185         .read32 = tpm_tcg_read32,
 186         .write32 = tpm_tcg_write32,
 187 };
 188 
 189 static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info)
 190 {
 191         struct tpm_tis_tcg_phy *phy;
 192         int irq = -1;
 193         int rc;
 194 
 195         rc = check_acpi_tpm2(dev);
 196         if (rc)
 197                 return rc;
 198 
 199         phy = devm_kzalloc(dev, sizeof(struct tpm_tis_tcg_phy), GFP_KERNEL);
 200         if (phy == NULL)
 201                 return -ENOMEM;
 202 
 203         phy->iobase = devm_ioremap_resource(dev, &tpm_info->res);
 204         if (IS_ERR(phy->iobase))
 205                 return PTR_ERR(phy->iobase);
 206 
 207         if (interrupts)
 208                 irq = tpm_info->irq;
 209 
 210         if (itpm || is_itpm(ACPI_COMPANION(dev)))
 211                 phy->priv.flags |= TPM_TIS_ITPM_WORKAROUND;
 212 
 213         return tpm_tis_core_init(dev, &phy->priv, irq, &tpm_tcg,
 214                                  ACPI_HANDLE(dev));
 215 }
 216 
 217 static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume);
 218 
 219 static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
 220                             const struct pnp_device_id *pnp_id)
 221 {
 222         struct tpm_info tpm_info = {};
 223         struct resource *res;
 224 
 225         res = pnp_get_resource(pnp_dev, IORESOURCE_MEM, 0);
 226         if (!res)
 227                 return -ENODEV;
 228         tpm_info.res = *res;
 229 
 230         if (pnp_irq_valid(pnp_dev, 0))
 231                 tpm_info.irq = pnp_irq(pnp_dev, 0);
 232         else
 233                 tpm_info.irq = -1;
 234 
 235         return tpm_tis_init(&pnp_dev->dev, &tpm_info);
 236 }
 237 
 238 static struct pnp_device_id tpm_pnp_tbl[] = {
 239         {"PNP0C31", 0},         /* TPM */
 240         {"ATM1200", 0},         /* Atmel */
 241         {"IFX0102", 0},         /* Infineon */
 242         {"BCM0101", 0},         /* Broadcom */
 243         {"BCM0102", 0},         /* Broadcom */
 244         {"NSC1200", 0},         /* National */
 245         {"ICO0102", 0},         /* Intel */
 246         /* Add new here */
 247         {"", 0},                /* User Specified */
 248         {"", 0}                 /* Terminator */
 249 };
 250 MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl);
 251 
 252 static void tpm_tis_pnp_remove(struct pnp_dev *dev)
 253 {
 254         struct tpm_chip *chip = pnp_get_drvdata(dev);
 255 
 256         tpm_chip_unregister(chip);
 257         tpm_tis_remove(chip);
 258 }
 259 
 260 static struct pnp_driver tis_pnp_driver = {
 261         .name = "tpm_tis",
 262         .id_table = tpm_pnp_tbl,
 263         .probe = tpm_tis_pnp_init,
 264         .remove = tpm_tis_pnp_remove,
 265         .driver = {
 266                 .pm = &tpm_tis_pm,
 267         },
 268 };
 269 
 270 #define TIS_HID_USR_IDX (ARRAY_SIZE(tpm_pnp_tbl) - 2)
 271 module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id,
 272                     sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444);
 273 MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
 274 
 275 static struct platform_device *force_pdev;
 276 
 277 static int tpm_tis_plat_probe(struct platform_device *pdev)
 278 {
 279         struct tpm_info tpm_info = {};
 280         struct resource *res;
 281 
 282         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 283         if (res == NULL) {
 284                 dev_err(&pdev->dev, "no memory resource defined\n");
 285                 return -ENODEV;
 286         }
 287         tpm_info.res = *res;
 288 
 289         tpm_info.irq = platform_get_irq_optional(pdev, 0);
 290         if (tpm_info.irq <= 0) {
 291                 if (pdev != force_pdev)
 292                         tpm_info.irq = -1;
 293                 else
 294                         /* When forcing auto probe the IRQ */
 295                         tpm_info.irq = 0;
 296         }
 297 
 298         return tpm_tis_init(&pdev->dev, &tpm_info);
 299 }
 300 
 301 static int tpm_tis_plat_remove(struct platform_device *pdev)
 302 {
 303         struct tpm_chip *chip = dev_get_drvdata(&pdev->dev);
 304 
 305         tpm_chip_unregister(chip);
 306         tpm_tis_remove(chip);
 307 
 308         return 0;
 309 }
 310 
 311 #ifdef CONFIG_OF
 312 static const struct of_device_id tis_of_platform_match[] = {
 313         {.compatible = "tcg,tpm-tis-mmio"},
 314         {},
 315 };
 316 MODULE_DEVICE_TABLE(of, tis_of_platform_match);
 317 #endif
 318 
 319 static struct platform_driver tis_drv = {
 320         .probe = tpm_tis_plat_probe,
 321         .remove = tpm_tis_plat_remove,
 322         .driver = {
 323                 .name           = "tpm_tis",
 324                 .pm             = &tpm_tis_pm,
 325                 .of_match_table = of_match_ptr(tis_of_platform_match),
 326                 .acpi_match_table = ACPI_PTR(tpm_acpi_tbl),
 327         },
 328 };
 329 
 330 static int tpm_tis_force_device(void)
 331 {
 332         struct platform_device *pdev;
 333         static const struct resource x86_resources[] = {
 334                 {
 335                         .start = 0xFED40000,
 336                         .end = 0xFED40000 + TIS_MEM_LEN - 1,
 337                         .flags = IORESOURCE_MEM,
 338                 },
 339         };
 340 
 341         if (!force)
 342                 return 0;
 343 
 344         /* The driver core will match the name tpm_tis of the device to
 345          * the tpm_tis platform driver and complete the setup via
 346          * tpm_tis_plat_probe
 347          */
 348         pdev = platform_device_register_simple("tpm_tis", -1, x86_resources,
 349                                                ARRAY_SIZE(x86_resources));
 350         if (IS_ERR(pdev))
 351                 return PTR_ERR(pdev);
 352         force_pdev = pdev;
 353 
 354         return 0;
 355 }
 356 
 357 static int __init init_tis(void)
 358 {
 359         int rc;
 360 
 361         rc = tpm_tis_force_device();
 362         if (rc)
 363                 goto err_force;
 364 
 365         rc = platform_driver_register(&tis_drv);
 366         if (rc)
 367                 goto err_platform;
 368 
 369 
 370         if (IS_ENABLED(CONFIG_PNP)) {
 371                 rc = pnp_register_driver(&tis_pnp_driver);
 372                 if (rc)
 373                         goto err_pnp;
 374         }
 375 
 376         return 0;
 377 
 378 err_pnp:
 379         platform_driver_unregister(&tis_drv);
 380 err_platform:
 381         if (force_pdev)
 382                 platform_device_unregister(force_pdev);
 383 err_force:
 384         return rc;
 385 }
 386 
 387 static void __exit cleanup_tis(void)
 388 {
 389         pnp_unregister_driver(&tis_pnp_driver);
 390         platform_driver_unregister(&tis_drv);
 391 
 392         if (force_pdev)
 393                 platform_device_unregister(force_pdev);
 394 }
 395 
 396 module_init(init_tis);
 397 module_exit(cleanup_tis);
 398 MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
 399 MODULE_DESCRIPTION("TPM Driver");
 400 MODULE_VERSION("2.0");
 401 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */