1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * driver for mmio TCG/TIS TPM (trusted platform module).
4  *
5  * Specifications at www.trustedcomputinggroup.org
6  */
7 
8 #include <common.h>
9 #include <dm.h>
10 #include <log.h>
11 #include <tpm-v2.h>
12 #include <linux/bitops.h>
13 #include <linux/compiler.h>
14 #include <linux/delay.h>
15 #include <linux/errno.h>
16 #include <linux/types.h>
17 #include <linux/io.h>
18 #include <linux/unaligned/be_byteshift.h>
19 #include "tpm_tis.h"
20 #include "tpm_internal.h"
21 
22 /**
23  * struct tpm_tis_chip_data - Information about an MMIO TPM
24  * @pcr_count:          Number of PCR per bank
25  * @pcr_select_min:	Minimum size in bytes of the pcrSelect array
26  * @iobase:		Base address
27  */
28 struct tpm_tis_chip_data {
29 	unsigned int pcr_count;
30 	unsigned int pcr_select_min;
31 	void __iomem *iobase;
32 };
33 
mmio_read_bytes(struct udevice * dev,u32 addr,u16 len,u8 * result)34 static int mmio_read_bytes(struct udevice *dev, u32 addr, u16 len,
35 			   u8 *result)
36 {
37 	struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(dev);
38 
39 	while (len--)
40 		*result++ = ioread8(drv_data->iobase + addr);
41 
42 	return 0;
43 }
44 
mmio_write_bytes(struct udevice * dev,u32 addr,u16 len,const u8 * value)45 static int mmio_write_bytes(struct udevice *dev, u32 addr, u16 len,
46 			    const u8 *value)
47 {
48 	struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(dev);
49 
50 	while (len--)
51 		iowrite8(*value++, drv_data->iobase + addr);
52 
53 	return 0;
54 }
55 
mmio_read32(struct udevice * dev,u32 addr,u32 * result)56 static int mmio_read32(struct udevice *dev, u32 addr, u32 *result)
57 {
58 	struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(dev);
59 
60 	*result = ioread32(drv_data->iobase + addr);
61 
62 	return 0;
63 }
64 
mmio_write32(struct udevice * dev,u32 addr,u32 value)65 static int mmio_write32(struct udevice *dev, u32 addr, u32 value)
66 {
67 	struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(dev);
68 
69 	iowrite32(value, drv_data->iobase + addr);
70 
71 	return 0;
72 }
73 
74 static struct tpm_tis_phy_ops phy_ops = {
75 	.read_bytes = mmio_read_bytes,
76 	.write_bytes = mmio_write_bytes,
77 	.read32 = mmio_read32,
78 	.write32 = mmio_write32,
79 };
80 
tpm_tis_probe(struct udevice * dev)81 static int tpm_tis_probe(struct udevice *dev)
82 {
83 	struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(dev);
84 	struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
85 	int ret = 0;
86 	fdt_addr_t ioaddr;
87 	u64 sz;
88 
89 	ioaddr = dev_read_addr(dev);
90 	if (ioaddr == FDT_ADDR_T_NONE)
91 		return log_msg_ret("ioaddr", -EINVAL);
92 
93 	ret = dev_read_u64(dev, "reg", &sz);
94 	if (ret)
95 		return -EINVAL;
96 
97 	drv_data->iobase = ioremap(ioaddr, sz);
98 	tpm_tis_ops_register(dev, &phy_ops);
99 	ret = tpm_tis_init(dev);
100 	if (ret)
101 		goto iounmap;
102 
103 	priv->pcr_count = drv_data->pcr_count;
104 	priv->pcr_select_min = drv_data->pcr_select_min;
105 	/*
106 	 * Although the driver probably works with a TPMv1 our Kconfig
107 	 * limits the driver to TPMv2 only
108 	 */
109 	priv->version = TPM_V2;
110 
111 	return ret;
112 iounmap:
113 	iounmap(drv_data->iobase);
114 
115 	return -EINVAL;
116 }
117 
tpm_tis_remove(struct udevice * dev)118 static int tpm_tis_remove(struct udevice *dev)
119 {
120 	struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(dev);
121 	int ret;
122 
123 	ret = tpm_tis_cleanup(dev);
124 
125 	iounmap(drv_data->iobase);
126 
127 	return ret;
128 }
129 
130 static const struct tpm_ops tpm_tis_ops = {
131 	.open		= tpm_tis_open,
132 	.close		= tpm_tis_close,
133 	.get_desc	= tpm_tis_get_desc,
134 	.send		= tpm_tis_send,
135 	.recv		= tpm_tis_recv,
136 	.cleanup	= tpm_tis_cleanup,
137 };
138 
139 static const struct tpm_tis_chip_data tpm_tis_std_chip_data = {
140 	.pcr_count = 24,
141 	.pcr_select_min = 3,
142 };
143 
144 static const struct udevice_id tpm_tis_ids[] = {
145 	{
146 		.compatible = "tcg,tpm-tis-mmio",
147 		.data = (ulong)&tpm_tis_std_chip_data,
148 	},
149 	{ }
150 };
151 
152 U_BOOT_DRIVER(tpm_tis_mmio) = {
153 	.name   = "tpm_tis_mmio",
154 	.id     = UCLASS_TPM,
155 	.of_match = tpm_tis_ids,
156 	.ops    = &tpm_tis_ops,
157 	.probe	= tpm_tis_probe,
158 	.remove	= tpm_tis_remove,
159 	.priv_auto	= sizeof(struct tpm_chip),
160 };
161