]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/tpm/tis_i2c.c
arm: mx5: Add fuse supply enable in fsl_iim
[karo-tx-uboot.git] / drivers / tpm / tis_i2c.c
1 /*
2  * Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6
7 #include <config.h>
8 #include <common.h>
9 #include <fdtdec.h>
10 #include <i2c.h>
11 #include "slb9635_i2c/tpm.h"
12
13 DECLARE_GLOBAL_DATA_PTR;
14
15 /* TPM configuration */
16 struct tpm {
17         int i2c_bus;
18         int slave_addr;
19         char inited;
20         int old_bus;
21 } tpm;
22
23
24 static int tpm_select(void)
25 {
26         int ret;
27
28         tpm.old_bus = i2c_get_bus_num();
29         if (tpm.old_bus != tpm.i2c_bus) {
30                 ret = i2c_set_bus_num(tpm.i2c_bus);
31                 if (ret) {
32                         debug("%s: Fail to set i2c bus %d\n", __func__,
33                               tpm.i2c_bus);
34                         return -1;
35                 }
36         }
37         return 0;
38 }
39
40 static int tpm_deselect(void)
41 {
42         int ret;
43
44         if (tpm.old_bus != i2c_get_bus_num()) {
45                 ret = i2c_set_bus_num(tpm.old_bus);
46                 if (ret) {
47                         debug("%s: Fail to restore i2c bus %d\n",
48                               __func__, tpm.old_bus);
49                         return -1;
50                 }
51         }
52         tpm.old_bus = -1;
53         return 0;
54 }
55
56 /**
57  * Decode TPM configuration.
58  *
59  * @param dev   Returns a configuration of TPM device
60  * @return 0 if ok, -1 on error
61  */
62 static int tpm_decode_config(struct tpm *dev)
63 {
64 #ifdef CONFIG_OF_CONTROL
65         const void *blob = gd->fdt_blob;
66         int node, parent;
67         int i2c_bus;
68
69         node = fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM);
70         if (node < 0) {
71                 node = fdtdec_next_compatible(blob, 0,
72                                               COMPAT_INFINEON_SLB9645_TPM);
73         }
74         if (node < 0) {
75                 debug("%s: Node not found\n", __func__);
76                 return -1;
77         }
78         parent = fdt_parent_offset(blob, node);
79         if (parent < 0) {
80                 debug("%s: Cannot find node parent\n", __func__);
81                 return -1;
82         }
83         i2c_bus = i2c_get_bus_num_fdt(parent);
84         if (i2c_bus < 0)
85                 return -1;
86         dev->i2c_bus = i2c_bus;
87         dev->slave_addr = fdtdec_get_addr(blob, node, "reg");
88 #else
89         dev->i2c_bus = CONFIG_INFINEON_TPM_I2C_BUS;
90         dev->slave_addr = CONFIG_INFINEON_TPM_I2C_ADDR;
91 #endif
92         return 0;
93 }
94
95 int tis_init(void)
96 {
97         if (tpm.inited)
98                 return 0;
99
100         if (tpm_decode_config(&tpm))
101                 return -1;
102
103         if (tpm_select())
104                 return -1;
105
106         /*
107          * Probe TPM twice; the first probing might fail because TPM is asleep,
108          * and the probing can wake up TPM.
109          */
110         if (i2c_probe(tpm.slave_addr) && i2c_probe(tpm.slave_addr)) {
111                 debug("%s: fail to probe i2c addr 0x%x\n", __func__,
112                       tpm.slave_addr);
113                 return -1;
114         }
115
116         tpm_deselect();
117
118         tpm.inited = 1;
119
120         return 0;
121 }
122
123 int tis_open(void)
124 {
125         int rc;
126
127         if (!tpm.inited)
128                 return -1;
129
130         if (tpm_select())
131                 return -1;
132
133         rc = tpm_open(tpm.slave_addr);
134
135         tpm_deselect();
136
137         return rc;
138 }
139
140 int tis_close(void)
141 {
142         if (!tpm.inited)
143                 return -1;
144
145         if (tpm_select())
146                 return -1;
147
148         tpm_close();
149
150         tpm_deselect();
151
152         return 0;
153 }
154
155 int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size,
156                 uint8_t *recvbuf, size_t *rbuf_len)
157 {
158         int len;
159         uint8_t buf[4096];
160
161         if (!tpm.inited)
162                 return -1;
163
164         if (sizeof(buf) < sbuf_size)
165                 return -1;
166
167         memcpy(buf, sendbuf, sbuf_size);
168
169         if (tpm_select())
170                 return -1;
171
172         len = tpm_transmit(buf, sbuf_size);
173
174         tpm_deselect();
175
176         if (len < 10) {
177                 *rbuf_len = 0;
178                 return -1;
179         }
180
181         memcpy(recvbuf, buf, len);
182         *rbuf_len = len;
183
184         return 0;
185 }