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