blob: a646ce41ff4e05e8023eb10f7322de8ed5015c53 [file] [log] [blame]
Ilias Apalodimase61c48d2021-11-09 09:02:18 +02001// 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 */
28struct tpm_tis_chip_data {
29 unsigned int pcr_count;
30 unsigned int pcr_select_min;
31 void __iomem *iobase;
32};
33
34static 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
45static 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
56static 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
65static 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
74static 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
81static 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;
112iounmap:
113 iounmap(drv_data->iobase);
114
115 return -EINVAL;
116}
117
118static int tpm_tis_remove(struct udevice *dev)
119{
120 struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(dev);
Heinrich Schuchardt938a03f2021-11-29 00:03:44 +0100121 int ret;
122
123 ret = tpm_tis_cleanup(dev);
Ilias Apalodimase61c48d2021-11-09 09:02:18 +0200124
125 iounmap(drv_data->iobase);
126
Heinrich Schuchardt938a03f2021-11-29 00:03:44 +0100127 return ret;
Ilias Apalodimase61c48d2021-11-09 09:02:18 +0200128}
129
130static 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
139static const struct tpm_tis_chip_data tpm_tis_std_chip_data = {
140 .pcr_count = 24,
141 .pcr_select_min = 3,
142};
143
144static 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
152U_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};