| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2005, 2006 IBM Corporation |
|---|
| 3 | 4 | * Copyright (C) 2014, 2015 Intel Corporation |
|---|
| .. | .. |
|---|
| 13 | 14 | * |
|---|
| 14 | 15 | * This device driver implements the TPM interface as defined in |
|---|
| 15 | 16 | * the TCG TPM Interface Spec version 1.2, revision 1.0. |
|---|
| 16 | | - * |
|---|
| 17 | | - * This program is free software; you can redistribute it and/or |
|---|
| 18 | | - * modify it under the terms of the GNU General Public License as |
|---|
| 19 | | - * published by the Free Software Foundation, version 2 of the |
|---|
| 20 | | - * License. |
|---|
| 21 | 17 | */ |
|---|
| 22 | 18 | #include <linux/init.h> |
|---|
| 23 | 19 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 54 | 50 | return container_of(data, struct tpm_tis_tcg_phy, priv); |
|---|
| 55 | 51 | } |
|---|
| 56 | 52 | |
|---|
| 57 | | -#ifdef CONFIG_PREEMPT_RT_FULL |
|---|
| 58 | | -/* |
|---|
| 59 | | - * Flushes previous write operations to chip so that a subsequent |
|---|
| 60 | | - * ioread*()s won't stall a cpu. |
|---|
| 61 | | - */ |
|---|
| 62 | | -static inline void tpm_tis_flush(void __iomem *iobase) |
|---|
| 63 | | -{ |
|---|
| 64 | | - ioread8(iobase + TPM_ACCESS(0)); |
|---|
| 65 | | -} |
|---|
| 66 | | -#else |
|---|
| 67 | | -#define tpm_tis_flush(iobase) do { } while (0) |
|---|
| 68 | | -#endif |
|---|
| 69 | | - |
|---|
| 70 | | -static inline void tpm_tis_iowrite8(u8 b, void __iomem *iobase, u32 addr) |
|---|
| 71 | | -{ |
|---|
| 72 | | - iowrite8(b, iobase + addr); |
|---|
| 73 | | - tpm_tis_flush(iobase); |
|---|
| 74 | | -} |
|---|
| 75 | | - |
|---|
| 76 | | -static inline void tpm_tis_iowrite32(u32 b, void __iomem *iobase, u32 addr) |
|---|
| 77 | | -{ |
|---|
| 78 | | - iowrite32(b, iobase + addr); |
|---|
| 79 | | - tpm_tis_flush(iobase); |
|---|
| 80 | | -} |
|---|
| 81 | | - |
|---|
| 82 | 53 | static int interrupts = -1; |
|---|
| 83 | 54 | module_param(interrupts, int, 0444); |
|---|
| 84 | 55 | MODULE_PARM_DESC(interrupts, "Enable interrupts"); |
|---|
| .. | .. |
|---|
| 110 | 81 | .matches = { |
|---|
| 111 | 82 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
|---|
| 112 | 83 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T490s"), |
|---|
| 84 | + }, |
|---|
| 85 | + }, |
|---|
| 86 | + { |
|---|
| 87 | + .callback = tpm_tis_disable_irq, |
|---|
| 88 | + .ident = "ThinkStation P360 Tiny", |
|---|
| 89 | + .matches = { |
|---|
| 90 | + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
|---|
| 91 | + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkStation P360 Tiny"), |
|---|
| 92 | + }, |
|---|
| 93 | + }, |
|---|
| 94 | + { |
|---|
| 95 | + .callback = tpm_tis_disable_irq, |
|---|
| 96 | + .ident = "ThinkPad L490", |
|---|
| 97 | + .matches = { |
|---|
| 98 | + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
|---|
| 99 | + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L490"), |
|---|
| 113 | 100 | }, |
|---|
| 114 | 101 | }, |
|---|
| 115 | 102 | {} |
|---|
| .. | .. |
|---|
| 154 | 141 | const struct acpi_device_id *aid = acpi_match_device(tpm_acpi_tbl, dev); |
|---|
| 155 | 142 | struct acpi_table_tpm2 *tbl; |
|---|
| 156 | 143 | acpi_status st; |
|---|
| 144 | + int ret = 0; |
|---|
| 157 | 145 | |
|---|
| 158 | 146 | if (!aid || aid->driver_data != DEVICE_IS_TPM2) |
|---|
| 159 | 147 | return 0; |
|---|
| .. | .. |
|---|
| 161 | 149 | /* If the ACPI TPM2 signature is matched then a global ACPI_SIG_TPM2 |
|---|
| 162 | 150 | * table is mandatory |
|---|
| 163 | 151 | */ |
|---|
| 164 | | - st = |
|---|
| 165 | | - acpi_get_table(ACPI_SIG_TPM2, 1, (struct acpi_table_header **)&tbl); |
|---|
| 152 | + st = acpi_get_table(ACPI_SIG_TPM2, 1, (struct acpi_table_header **)&tbl); |
|---|
| 166 | 153 | if (ACPI_FAILURE(st) || tbl->header.length < sizeof(*tbl)) { |
|---|
| 167 | 154 | dev_err(dev, FW_BUG "failed to get TPM2 ACPI table\n"); |
|---|
| 168 | 155 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 170 | 157 | |
|---|
| 171 | 158 | /* The tpm2_crb driver handles this device */ |
|---|
| 172 | 159 | if (tbl->start_method != ACPI_TPM2_MEMORY_MAPPED) |
|---|
| 173 | | - return -ENODEV; |
|---|
| 160 | + ret = -ENODEV; |
|---|
| 174 | 161 | |
|---|
| 175 | | - return 0; |
|---|
| 162 | + acpi_put_table((struct acpi_table_header *)tbl); |
|---|
| 163 | + return ret; |
|---|
| 176 | 164 | } |
|---|
| 177 | 165 | #else |
|---|
| 178 | 166 | static int check_acpi_tpm2(struct device *dev) |
|---|
| .. | .. |
|---|
| 198 | 186 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); |
|---|
| 199 | 187 | |
|---|
| 200 | 188 | while (len--) |
|---|
| 201 | | - tpm_tis_iowrite8(*value++, phy->iobase, addr); |
|---|
| 189 | + iowrite8(*value++, phy->iobase + addr); |
|---|
| 202 | 190 | |
|---|
| 203 | 191 | return 0; |
|---|
| 204 | 192 | } |
|---|
| .. | .. |
|---|
| 225 | 213 | { |
|---|
| 226 | 214 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); |
|---|
| 227 | 215 | |
|---|
| 228 | | - tpm_tis_iowrite32(value, phy->iobase, addr); |
|---|
| 216 | + iowrite32(value, phy->iobase + addr); |
|---|
| 229 | 217 | |
|---|
| 230 | 218 | return 0; |
|---|
| 231 | 219 | } |
|---|
| .. | .. |
|---|
| 289 | 277 | return tpm_tis_init(&pnp_dev->dev, &tpm_info); |
|---|
| 290 | 278 | } |
|---|
| 291 | 279 | |
|---|
| 280 | +/* |
|---|
| 281 | + * There is a known bug caused by 93e1b7d42e1e ("[PATCH] tpm: add HID module |
|---|
| 282 | + * parameter"). This commit added IFX0102 device ID, which is also used by |
|---|
| 283 | + * tpm_infineon but ignored to add quirks to probe which driver ought to be |
|---|
| 284 | + * used. |
|---|
| 285 | + */ |
|---|
| 286 | + |
|---|
| 292 | 287 | static struct pnp_device_id tpm_pnp_tbl[] = { |
|---|
| 293 | 288 | {"PNP0C31", 0}, /* TPM */ |
|---|
| 294 | 289 | {"ATM1200", 0}, /* Atmel */ |
|---|
| .. | .. |
|---|
| 340 | 335 | } |
|---|
| 341 | 336 | tpm_info.res = *res; |
|---|
| 342 | 337 | |
|---|
| 343 | | - tpm_info.irq = platform_get_irq(pdev, 0); |
|---|
| 338 | + tpm_info.irq = platform_get_irq_optional(pdev, 0); |
|---|
| 344 | 339 | if (tpm_info.irq <= 0) { |
|---|
| 345 | 340 | if (pdev != force_pdev) |
|---|
| 346 | 341 | tpm_info.irq = -1; |
|---|