common: Drop display_options.h from common header
[platform/kernel/u-boot.git] / drivers / tpm / tpm2_tis_i2c.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2022 IBM Corp.
4  */
5
6 #include <common.h>
7 #include <dm.h>
8 #include <fdtdec.h>
9 #include <i2c.h>
10 #include <log.h>
11 #include <tpm-v2.h>
12 #include <linux/bitops.h>
13 #include <linux/delay.h>
14 #include <linux/errno.h>
15 #include <linux/compiler.h>
16 #include <linux/types.h>
17 #include <linux/unaligned/be_byteshift.h>
18 #include <asm-generic/gpio.h>
19
20 #include "tpm_tis.h"
21 #include "tpm_internal.h"
22
23 struct tpm_tis_chip_data {
24         unsigned int pcr_count;
25         unsigned int pcr_select_min;
26 };
27
28 static uint tpm_tis_i2c_address_to_register(u32 addr)
29 {
30         addr &= 0xFFF;
31
32         /*
33          * Adapt register addresses that have changed compared to older TIS
34          * version.
35          */
36         switch (addr) {
37         case TPM_ACCESS(0):
38                 return 0x04;
39         case TPM_DID_VID(0):
40                 return 0x48;
41         case TPM_RID(0):
42                 return 0x4C;
43         default:
44                 return addr;
45         }
46 }
47
48 static int tpm_tis_i2c_read(struct udevice *dev, u32 addr, u16 len, u8 *in)
49 {
50         int rc;
51         int count = 0;
52         uint reg = tpm_tis_i2c_address_to_register(addr);
53
54         do {
55                 rc = dm_i2c_read(dev, reg, in, len);
56                 udelay(SLEEP_DURATION_US);
57         } while (rc && count++ < MAX_COUNT);
58
59         return rc;
60 }
61
62 static int tpm_tis_i2c_write(struct udevice *dev, u32 addr, u16 len,
63                              const u8 *out)
64 {
65         int rc;
66         int count = 0;
67         uint reg = tpm_tis_i2c_address_to_register(addr);
68
69         do {
70                 rc = dm_i2c_write(dev, reg, out, len);
71                 udelay(SLEEP_DURATION_US);
72         } while (rc && count++ < MAX_COUNT);
73
74         return rc;
75 }
76
77 static int tpm_tis_i2c_read32(struct udevice *dev, u32 addr, u32 *result)
78 {
79         __le32 result_le;
80         int rc;
81
82         rc = tpm_tis_i2c_read(dev, addr, sizeof(u32), (u8 *)&result_le);
83         if (!rc)
84                 *result = le32_to_cpu(result_le);
85
86         return rc;
87 }
88
89 static int tpm_tis_i2c_write32(struct udevice *dev, u32 addr, u32 value)
90 {
91         __le32 value_le = cpu_to_le32(value);
92
93         return tpm_tis_i2c_write(dev, addr, sizeof(value), (u8 *)&value_le);
94 }
95
96 static struct tpm_tis_phy_ops phy_ops = {
97         .read_bytes = tpm_tis_i2c_read,
98         .write_bytes = tpm_tis_i2c_write,
99         .read32 = tpm_tis_i2c_read32,
100         .write32 = tpm_tis_i2c_write32,
101 };
102
103 static int tpm_tis_i2c_probe(struct udevice *udev)
104 {
105         struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(udev);
106         struct tpm_chip_priv *priv = dev_get_uclass_priv(udev);
107         int rc;
108         u8 loc = 0;
109
110         tpm_tis_ops_register(udev, &phy_ops);
111
112         /*
113          * Force locality 0. The core driver doesn't actually write the
114          * locality register and instead just reads/writes various access
115          * bits of the selected locality.
116          */
117         rc = dm_i2c_write(udev, 0, &loc, 1);
118         if (rc)
119                 return rc;
120
121         rc = tpm_tis_init(udev);
122         if (rc)
123                 return rc;
124
125         priv->pcr_count = drv_data->pcr_count;
126         priv->pcr_select_min = drv_data->pcr_select_min;
127         priv->version = TPM_V2;
128
129         return 0;
130 }
131
132 static int tpm_tis_i2c_remove(struct udevice *udev)
133 {
134         return tpm_tis_cleanup(udev);
135 }
136
137 static const struct tpm_ops tpm_tis_i2c_ops = {
138         .open = tpm_tis_open,
139         .close = tpm_tis_close,
140         .get_desc = tpm_tis_get_desc,
141         .send = tpm_tis_send,
142         .recv = tpm_tis_recv,
143         .cleanup = tpm_tis_cleanup,
144 };
145
146 static const struct tpm_tis_chip_data tpm_tis_std_chip_data = {
147         .pcr_count = 24,
148         .pcr_select_min = 3,
149 };
150
151 static const struct udevice_id tpm_tis_i2c_ids[] = {
152         {
153                 .compatible = "nuvoton,npct75x",
154                 .data = (ulong)&tpm_tis_std_chip_data,
155         },
156         {
157                 .compatible = "tcg,tpm-tis-i2c",
158                 .data = (ulong)&tpm_tis_std_chip_data,
159         },
160         { }
161 };
162
163 U_BOOT_DRIVER(tpm_tis_i2c) = {
164         .name = "tpm_tis_i2c",
165         .id = UCLASS_TPM,
166         .of_match = tpm_tis_i2c_ids,
167         .ops = &tpm_tis_i2c_ops,
168         .probe = tpm_tis_i2c_probe,
169         .remove = tpm_tis_i2c_remove,
170         .priv_auto = sizeof(struct tpm_chip),
171 };