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