1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2005, 2006 IBM Corporation
4 * Copyright (C) 2014, 2015 Intel Corporation
7 * Leendert van Doorn <leendert@watson.ibm.com>
8 * Kylene Hall <kjhall@us.ibm.com>
10 * Maintained by: <tpmdd-devel@lists.sourceforge.net>
12 * Device driver for TCG/TCPA TPM (trusted platform module).
13 * Specifications at www.trustedcomputinggroup.org
15 * This device driver implements the TPM interface as defined in
16 * the TCG TPM Interface Spec version 1.2, revision 1.0.
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>
28 #include <linux/of_device.h>
29 #include <linux/kernel.h>
30 #include <linux/dmi.h>
32 #include "tpm_tis_core.h"
36 /* irq > 0 means: use irq $irq;
37 * irq = 0 means: autoprobe for an irq;
38 * irq = -1 means: no irq support
43 struct tpm_tis_tcg_phy
{
44 struct tpm_tis_data priv
;
48 static inline struct tpm_tis_tcg_phy
*to_tpm_tis_tcg_phy(struct tpm_tis_data
*data
)
50 return container_of(data
, struct tpm_tis_tcg_phy
, priv
);
53 static int interrupts
= -1;
54 module_param(interrupts
, int, 0444);
55 MODULE_PARM_DESC(interrupts
, "Enable interrupts");
58 module_param(itpm
, bool, 0444);
59 MODULE_PARM_DESC(itpm
, "Force iTPM workarounds (found on some Lenovo laptops)");
63 module_param(force
, bool, 0444);
64 MODULE_PARM_DESC(force
, "Force device probe rather than using ACPI entry");
67 static int tpm_tis_disable_irq(const struct dmi_system_id
*d
)
69 if (interrupts
== -1) {
70 pr_notice("tpm_tis: %s detected: disabling interrupts.\n", d
->ident
);
77 static const struct dmi_system_id tpm_tis_dmi_table
[] = {
79 .callback
= tpm_tis_disable_irq
,
80 .ident
= "ThinkPad T490s",
82 DMI_MATCH(DMI_SYS_VENDOR
, "LENOVO"),
83 DMI_MATCH(DMI_PRODUCT_VERSION
, "ThinkPad T490s"),
89 #if defined(CONFIG_PNP) && defined(CONFIG_ACPI)
90 static int has_hid(struct acpi_device
*dev
, const char *hid
)
92 struct acpi_hardware_id
*id
;
94 list_for_each_entry(id
, &dev
->pnp
.ids
, list
)
95 if (!strcmp(hid
, id
->id
))
101 static inline int is_itpm(struct acpi_device
*dev
)
105 return has_hid(dev
, "INTC0102");
108 static inline int is_itpm(struct acpi_device
*dev
)
114 #if defined(CONFIG_ACPI)
115 #define DEVICE_IS_TPM2 1
117 static const struct acpi_device_id tpm_acpi_tbl
[] = {
118 {"MSFT0101", DEVICE_IS_TPM2
},
121 MODULE_DEVICE_TABLE(acpi
, tpm_acpi_tbl
);
123 static int check_acpi_tpm2(struct device
*dev
)
125 const struct acpi_device_id
*aid
= acpi_match_device(tpm_acpi_tbl
, dev
);
126 struct acpi_table_tpm2
*tbl
;
129 if (!aid
|| aid
->driver_data
!= DEVICE_IS_TPM2
)
132 /* If the ACPI TPM2 signature is matched then a global ACPI_SIG_TPM2
136 acpi_get_table(ACPI_SIG_TPM2
, 1, (struct acpi_table_header
**)&tbl
);
137 if (ACPI_FAILURE(st
) || tbl
->header
.length
< sizeof(*tbl
)) {
138 dev_err(dev
, FW_BUG
"failed to get TPM2 ACPI table\n");
142 /* The tpm2_crb driver handles this device */
143 if (tbl
->start_method
!= ACPI_TPM2_MEMORY_MAPPED
)
149 static int check_acpi_tpm2(struct device
*dev
)
155 static int tpm_tcg_read_bytes(struct tpm_tis_data
*data
, u32 addr
, u16 len
,
158 struct tpm_tis_tcg_phy
*phy
= to_tpm_tis_tcg_phy(data
);
161 *result
++ = ioread8(phy
->iobase
+ addr
);
166 static int tpm_tcg_write_bytes(struct tpm_tis_data
*data
, u32 addr
, u16 len
,
169 struct tpm_tis_tcg_phy
*phy
= to_tpm_tis_tcg_phy(data
);
172 iowrite8(*value
++, phy
->iobase
+ addr
);
177 static int tpm_tcg_read16(struct tpm_tis_data
*data
, u32 addr
, u16
*result
)
179 struct tpm_tis_tcg_phy
*phy
= to_tpm_tis_tcg_phy(data
);
181 *result
= ioread16(phy
->iobase
+ addr
);
186 static int tpm_tcg_read32(struct tpm_tis_data
*data
, u32 addr
, u32
*result
)
188 struct tpm_tis_tcg_phy
*phy
= to_tpm_tis_tcg_phy(data
);
190 *result
= ioread32(phy
->iobase
+ addr
);
195 static int tpm_tcg_write32(struct tpm_tis_data
*data
, u32 addr
, u32 value
)
197 struct tpm_tis_tcg_phy
*phy
= to_tpm_tis_tcg_phy(data
);
199 iowrite32(value
, phy
->iobase
+ addr
);
204 static const struct tpm_tis_phy_ops tpm_tcg
= {
205 .read_bytes
= tpm_tcg_read_bytes
,
206 .write_bytes
= tpm_tcg_write_bytes
,
207 .read16
= tpm_tcg_read16
,
208 .read32
= tpm_tcg_read32
,
209 .write32
= tpm_tcg_write32
,
212 static int tpm_tis_init(struct device
*dev
, struct tpm_info
*tpm_info
)
214 struct tpm_tis_tcg_phy
*phy
;
218 dmi_check_system(tpm_tis_dmi_table
);
220 rc
= check_acpi_tpm2(dev
);
224 phy
= devm_kzalloc(dev
, sizeof(struct tpm_tis_tcg_phy
), GFP_KERNEL
);
228 phy
->iobase
= devm_ioremap_resource(dev
, &tpm_info
->res
);
229 if (IS_ERR(phy
->iobase
))
230 return PTR_ERR(phy
->iobase
);
235 if (itpm
|| is_itpm(ACPI_COMPANION(dev
)))
236 phy
->priv
.flags
|= TPM_TIS_ITPM_WORKAROUND
;
238 return tpm_tis_core_init(dev
, &phy
->priv
, irq
, &tpm_tcg
,
242 static SIMPLE_DEV_PM_OPS(tpm_tis_pm
, tpm_pm_suspend
, tpm_tis_resume
);
244 static int tpm_tis_pnp_init(struct pnp_dev
*pnp_dev
,
245 const struct pnp_device_id
*pnp_id
)
247 struct tpm_info tpm_info
= {};
248 struct resource
*res
;
250 res
= pnp_get_resource(pnp_dev
, IORESOURCE_MEM
, 0);
255 if (pnp_irq_valid(pnp_dev
, 0))
256 tpm_info
.irq
= pnp_irq(pnp_dev
, 0);
260 return tpm_tis_init(&pnp_dev
->dev
, &tpm_info
);
264 * There is a known bug caused by 93e1b7d42e1e ("[PATCH] tpm: add HID module
265 * parameter"). This commit added IFX0102 device ID, which is also used by
266 * tpm_infineon but ignored to add quirks to probe which driver ought to be
270 static struct pnp_device_id tpm_pnp_tbl
[] = {
271 {"PNP0C31", 0}, /* TPM */
272 {"ATM1200", 0}, /* Atmel */
273 {"IFX0102", 0}, /* Infineon */
274 {"BCM0101", 0}, /* Broadcom */
275 {"BCM0102", 0}, /* Broadcom */
276 {"NSC1200", 0}, /* National */
277 {"ICO0102", 0}, /* Intel */
279 {"", 0}, /* User Specified */
280 {"", 0} /* Terminator */
282 MODULE_DEVICE_TABLE(pnp
, tpm_pnp_tbl
);
284 static void tpm_tis_pnp_remove(struct pnp_dev
*dev
)
286 struct tpm_chip
*chip
= pnp_get_drvdata(dev
);
288 tpm_chip_unregister(chip
);
289 tpm_tis_remove(chip
);
292 static struct pnp_driver tis_pnp_driver
= {
294 .id_table
= tpm_pnp_tbl
,
295 .probe
= tpm_tis_pnp_init
,
296 .remove
= tpm_tis_pnp_remove
,
302 #define TIS_HID_USR_IDX (ARRAY_SIZE(tpm_pnp_tbl) - 2)
303 module_param_string(hid
, tpm_pnp_tbl
[TIS_HID_USR_IDX
].id
,
304 sizeof(tpm_pnp_tbl
[TIS_HID_USR_IDX
].id
), 0444);
305 MODULE_PARM_DESC(hid
, "Set additional specific HID for this driver to probe");
307 static struct platform_device
*force_pdev
;
309 static int tpm_tis_plat_probe(struct platform_device
*pdev
)
311 struct tpm_info tpm_info
= {};
312 struct resource
*res
;
314 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
316 dev_err(&pdev
->dev
, "no memory resource defined\n");
321 tpm_info
.irq
= platform_get_irq_optional(pdev
, 0);
322 if (tpm_info
.irq
<= 0) {
323 if (pdev
!= force_pdev
)
326 /* When forcing auto probe the IRQ */
330 return tpm_tis_init(&pdev
->dev
, &tpm_info
);
333 static int tpm_tis_plat_remove(struct platform_device
*pdev
)
335 struct tpm_chip
*chip
= dev_get_drvdata(&pdev
->dev
);
337 tpm_chip_unregister(chip
);
338 tpm_tis_remove(chip
);
344 static const struct of_device_id tis_of_platform_match
[] = {
345 {.compatible
= "tcg,tpm-tis-mmio"},
348 MODULE_DEVICE_TABLE(of
, tis_of_platform_match
);
351 static struct platform_driver tis_drv
= {
352 .probe
= tpm_tis_plat_probe
,
353 .remove
= tpm_tis_plat_remove
,
357 .of_match_table
= of_match_ptr(tis_of_platform_match
),
358 .acpi_match_table
= ACPI_PTR(tpm_acpi_tbl
),
362 static int tpm_tis_force_device(void)
364 struct platform_device
*pdev
;
365 static const struct resource x86_resources
[] = {
368 .end
= 0xFED40000 + TIS_MEM_LEN
- 1,
369 .flags
= IORESOURCE_MEM
,
376 /* The driver core will match the name tpm_tis of the device to
377 * the tpm_tis platform driver and complete the setup via
380 pdev
= platform_device_register_simple("tpm_tis", -1, x86_resources
,
381 ARRAY_SIZE(x86_resources
));
383 return PTR_ERR(pdev
);
389 static int __init
init_tis(void)
393 rc
= tpm_tis_force_device();
397 rc
= platform_driver_register(&tis_drv
);
402 if (IS_ENABLED(CONFIG_PNP
)) {
403 rc
= pnp_register_driver(&tis_pnp_driver
);
411 platform_driver_unregister(&tis_drv
);
414 platform_device_unregister(force_pdev
);
419 static void __exit
cleanup_tis(void)
421 pnp_unregister_driver(&tis_pnp_driver
);
422 platform_driver_unregister(&tis_drv
);
425 platform_device_unregister(force_pdev
);
428 module_init(init_tis
);
429 module_exit(cleanup_tis
);
430 MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
431 MODULE_DESCRIPTION("TPM Driver");
432 MODULE_VERSION("2.0");
433 MODULE_LICENSE("GPL");