blob: dee5503c055f810412b954b468b43522dceab07c [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
Ilias Apalodimase61c48d2021-11-09 09:02:18 +02008#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 */
27struct tpm_tis_chip_data {
28 unsigned int pcr_count;
29 unsigned int pcr_select_min;
30 void __iomem *iobase;
31};
32
33static 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
44static 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
55static 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
64static 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
73static 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
80static 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;
111iounmap:
112 iounmap(drv_data->iobase);
113
114 return -EINVAL;
115}
116
117static int tpm_tis_remove(struct udevice *dev)
118{
119 struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(dev);
Heinrich Schuchardt938a03f2021-11-29 00:03:44 +0100120 int ret;
121
122 ret = tpm_tis_cleanup(dev);
Ilias Apalodimase61c48d2021-11-09 09:02:18 +0200123
124 iounmap(drv_data->iobase);
125
Heinrich Schuchardt938a03f2021-11-29 00:03:44 +0100126 return ret;
Ilias Apalodimase61c48d2021-11-09 09:02:18 +0200127}
128
129static 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
138static const struct tpm_tis_chip_data tpm_tis_std_chip_data = {
139 .pcr_count = 24,
140 .pcr_select_min = 3,
141};
142
143static 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
151U_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};