1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2020, Linaro Limited
4 *
5 * Based on the Linux TIS core interface and U-Boot original SPI TPM driver
6 */
7
8 #include <common.h>
9 #include <dm.h>
10 #include <tpm-v2.h>
11 #include <linux/delay.h>
12 #include <linux/unaligned/be_byteshift.h>
13 #include "tpm_tis.h"
14
tpm_tis_get_desc(struct udevice * dev,char * buf,int size)15 int tpm_tis_get_desc(struct udevice *dev, char *buf, int size)
16 {
17 struct tpm_chip *chip = dev_get_priv(dev);
18
19 if (size < 80)
20 return -ENOSPC;
21
22 return snprintf(buf, size,
23 "%s v2.0: VendorID 0x%04x, DeviceID 0x%04x, RevisionID 0x%02x [%s]",
24 dev->name, chip->vend_dev & 0xFFFF,
25 chip->vend_dev >> 16, chip->rid,
26 (chip->is_open ? "open" : "closed"));
27 }
28
29 /**
30 * tpm_tis_check_locality - Check the current TPM locality
31 *
32 * @dev: TPM device
33 * @loc: locality
34 *
35 * Return: True if the tested locality matches
36 */
tpm_tis_check_locality(struct udevice * dev,int loc)37 static bool tpm_tis_check_locality(struct udevice *dev, int loc)
38 {
39 struct tpm_chip *chip = dev_get_priv(dev);
40 struct tpm_tis_phy_ops *phy_ops = chip->phy_ops;
41 u8 locality;
42
43 phy_ops->read_bytes(dev, TPM_ACCESS(loc), 1, &locality);
44 if ((locality & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID |
45 TPM_ACCESS_REQUEST_USE)) ==
46 (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) {
47 chip->locality = loc;
48 return true;
49 }
50
51 return false;
52 }
53
54 /**
55 * tpm_tis_request_locality - Request a locality from the TPM
56 *
57 * @dev: TPM device
58 * @loc: requested locality
59 *
60 * Return: 0 on success -1 on failure
61 */
tpm_tis_request_locality(struct udevice * dev,int loc)62 int tpm_tis_request_locality(struct udevice *dev, int loc)
63 {
64 struct tpm_chip *chip = dev_get_priv(dev);
65 struct tpm_tis_phy_ops *phy_ops = chip->phy_ops;
66 u8 buf = TPM_ACCESS_REQUEST_USE;
67 unsigned long start, stop;
68
69 if (tpm_tis_check_locality(dev, loc))
70 return 0;
71
72 phy_ops->write_bytes(dev, TPM_ACCESS(loc), 1, &buf);
73 start = get_timer(0);
74 stop = chip->timeout_a;
75 do {
76 if (tpm_tis_check_locality(dev, loc))
77 return 0;
78 mdelay(TPM_TIMEOUT_MS);
79 } while (get_timer(start) < stop);
80
81 return -1;
82 }
83
84 /**
85 * tpm_tis_status - Check the current device status
86 *
87 * @dev: TPM device
88 * @status: return value of status
89 *
90 * Return: 0 on success, negative on failure
91 */
tpm_tis_status(struct udevice * dev,u8 * status)92 static int tpm_tis_status(struct udevice *dev, u8 *status)
93 {
94 struct tpm_chip *chip = dev_get_priv(dev);
95 struct tpm_tis_phy_ops *phy_ops = chip->phy_ops;
96
97 if (chip->locality < 0)
98 return -EINVAL;
99
100 phy_ops->read_bytes(dev, TPM_STS(chip->locality), 1, status);
101
102 if ((*status & TPM_STS_READ_ZERO)) {
103 log_err("TPM returned invalid status\n");
104 return -EINVAL;
105 }
106
107 return 0;
108 }
109
110 /**
111 * tpm_tis_release_locality - Release the requested locality
112 *
113 * @dev: TPM device
114 * @loc: requested locality
115 *
116 * Return: 0 on success, negative on failure
117 */
tpm_tis_release_locality(struct udevice * dev,int loc)118 int tpm_tis_release_locality(struct udevice *dev, int loc)
119 {
120 struct tpm_chip *chip = dev_get_priv(dev);
121 struct tpm_tis_phy_ops *phy_ops = chip->phy_ops;
122 u8 buf = TPM_ACCESS_ACTIVE_LOCALITY;
123 int ret;
124
125 if (chip->locality < 0)
126 return 0;
127
128 ret = phy_ops->write_bytes(dev, TPM_ACCESS(loc), 1, &buf);
129 chip->locality = -1;
130
131 return ret;
132 }
133
134 /**
135 * tpm_tis_wait_for_stat - Wait for TPM to become ready
136 *
137 * @dev: TPM device
138 * @mask: mask to match
139 * @timeout: timeout for retries
140 * @status: current status
141 *
142 * Return: 0 on success, negative on failure
143 */
tpm_tis_wait_for_stat(struct udevice * dev,u8 mask,unsigned long timeout,u8 * status)144 static int tpm_tis_wait_for_stat(struct udevice *dev, u8 mask,
145 unsigned long timeout, u8 *status)
146 {
147 unsigned long start = get_timer(0);
148 unsigned long stop = timeout;
149 int ret;
150
151 do {
152 mdelay(TPM_TIMEOUT_MS);
153 ret = tpm_tis_status(dev, status);
154 if (ret)
155 return ret;
156
157 if ((*status & mask) == mask)
158 return 0;
159 } while (get_timer(start) < stop);
160
161 return -ETIMEDOUT;
162 }
163
164 /**
165 * tpm_tis_get_burstcount - Get the burstcount for the data FIFO
166 *
167 * @dev: TPM device
168 * @burstcount: current burstcount
169 *
170 * Return: 0 on success, negative on failure
171 */
tpm_tis_get_burstcount(struct udevice * dev,size_t * burstcount)172 static int tpm_tis_get_burstcount(struct udevice *dev, size_t *burstcount)
173 {
174 struct tpm_chip *chip = dev_get_priv(dev);
175 struct tpm_tis_phy_ops *phy_ops = chip->phy_ops;
176 unsigned long start, stop;
177 u32 burst;
178
179 if (chip->locality < 0)
180 return -EINVAL;
181
182 /* wait for burstcount */
183 start = get_timer(0);
184 /*
185 * This is the TPMv2 defined timeout. Change this in case you want to
186 * make the driver compatile to TPMv1
187 */
188 stop = chip->timeout_a;
189 do {
190 phy_ops->read32(dev, TPM_STS(chip->locality), &burst);
191 *burstcount = (burst >> 8) & 0xFFFF;
192 if (*burstcount)
193 return 0;
194
195 mdelay(TPM_TIMEOUT_MS);
196 } while (get_timer(start) < stop);
197
198 return -ETIMEDOUT;
199 }
200
201 /**
202 * tpm_tis_ready - Cancel pending comands and get the device on a ready state
203 *
204 * @dev: TPM device
205 *
206 * Return: 0 on success, negative on failure
207 */
tpm_tis_ready(struct udevice * dev)208 static int tpm_tis_ready(struct udevice *dev)
209 {
210 struct tpm_chip *chip = dev_get_priv(dev);
211 struct tpm_tis_phy_ops *phy_ops = chip->phy_ops;
212 u8 data = TPM_STS_COMMAND_READY;
213
214 /* This will cancel any pending commands */
215 return phy_ops->write_bytes(dev, TPM_STS(chip->locality), 1, &data);
216 }
217
tpm_tis_send(struct udevice * dev,const u8 * buf,size_t len)218 int tpm_tis_send(struct udevice *dev, const u8 *buf, size_t len)
219 {
220 struct tpm_chip *chip = dev_get_priv(dev);
221 struct tpm_tis_phy_ops *phy_ops = chip->phy_ops;
222 size_t burstcnt, wr_size, sent = 0;
223 u8 data = TPM_STS_GO;
224 u8 status;
225 int ret;
226
227 if (!chip)
228 return -ENODEV;
229
230 ret = tpm_tis_request_locality(dev, 0);
231 if (ret < 0)
232 return -EBUSY;
233
234 ret = tpm_tis_status(dev, &status);
235 if (ret)
236 goto release_locality;
237
238 if (!(status & TPM_STS_COMMAND_READY)) {
239 ret = tpm_tis_ready(dev);
240 if (ret) {
241 log_err("Can't cancel previous TPM operation\n");
242 goto release_locality;
243 }
244 ret = tpm_tis_wait_for_stat(dev, TPM_STS_COMMAND_READY,
245 chip->timeout_b, &status);
246 if (ret) {
247 log_err("TPM not ready\n");
248 goto release_locality;
249 }
250 }
251
252 while (len > 0) {
253 ret = tpm_tis_get_burstcount(dev, &burstcnt);
254 if (ret)
255 goto release_locality;
256
257 wr_size = min(len, burstcnt);
258 ret = phy_ops->write_bytes(dev, TPM_DATA_FIFO(chip->locality),
259 wr_size, buf + sent);
260 if (ret < 0)
261 goto release_locality;
262
263 ret = tpm_tis_wait_for_stat(dev, TPM_STS_VALID,
264 chip->timeout_c, &status);
265 if (ret)
266 goto release_locality;
267
268 sent += wr_size;
269 len -= wr_size;
270 /* make sure the TPM expects more data */
271 if (len && !(status & TPM_STS_DATA_EXPECT)) {
272 ret = -EIO;
273 goto release_locality;
274 }
275 }
276
277 /*
278 * Make a final check ensuring everything is ok and the TPM expects no
279 * more data
280 */
281 ret = tpm_tis_wait_for_stat(dev, TPM_STS_VALID, chip->timeout_c,
282 &status);
283 if (ret)
284 goto release_locality;
285
286 if (status & TPM_STS_DATA_EXPECT) {
287 ret = -EIO;
288 goto release_locality;
289 }
290
291 ret = phy_ops->write_bytes(dev, TPM_STS(chip->locality), 1, &data);
292 if (ret)
293 goto release_locality;
294
295 return sent;
296
297 release_locality:
298 tpm_tis_ready(dev);
299 tpm_tis_release_locality(dev, chip->locality);
300
301 return ret;
302 }
303
tpm_tis_recv_data(struct udevice * dev,u8 * buf,size_t count)304 static int tpm_tis_recv_data(struct udevice *dev, u8 *buf, size_t count)
305 {
306 struct tpm_chip *chip = dev_get_priv(dev);
307 struct tpm_tis_phy_ops *phy_ops = chip->phy_ops;
308 int size = 0, len, ret;
309 size_t burstcnt;
310 u8 status;
311
312 while (size < count &&
313 tpm_tis_wait_for_stat(dev, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
314 chip->timeout_c, &status) == 0) {
315 ret = tpm_tis_get_burstcount(dev, &burstcnt);
316 if (ret)
317 return ret;
318
319 len = min_t(int, burstcnt, count - size);
320 ret = phy_ops->read_bytes(dev, TPM_DATA_FIFO(chip->locality),
321 len, buf + size);
322 if (ret < 0)
323 return ret;
324
325 size += len;
326 }
327
328 return size;
329 }
330
331 /**
332 * tpm_tis_recv - Receive data from a device
333 *
334 * @dev: TPM device
335 * @buf: buffer to copy data
336 * @size: buffer size
337 *
338 * Return: bytes read or negative on failure
339 */
tpm_tis_recv(struct udevice * dev,u8 * buf,size_t count)340 int tpm_tis_recv(struct udevice *dev, u8 *buf, size_t count)
341 {
342 struct tpm_chip *chip = dev_get_priv(dev);
343 int size, expected;
344
345 if (count < TPM_HEADER_SIZE)
346 return -E2BIG;
347
348 size = tpm_tis_recv_data(dev, buf, TPM_HEADER_SIZE);
349 if (size < TPM_HEADER_SIZE) {
350 log_err("TPM error, unable to read header\n");
351 goto out;
352 }
353
354 expected = get_unaligned_be32(buf + TPM_CMD_COUNT_OFFSET);
355 if (expected > count) {
356 size = -EIO;
357 log_warning("Too much data: %d > %zu\n", expected, count);
358 goto out;
359 }
360
361 size += tpm_tis_recv_data(dev, &buf[TPM_HEADER_SIZE],
362 expected - TPM_HEADER_SIZE);
363 if (size < expected) {
364 log(LOGC_NONE, LOGL_ERR,
365 "TPM error, unable to read remaining bytes of result\n");
366 size = -EIO;
367 goto out;
368 }
369
370 out:
371 tpm_tis_ready(dev);
372 /* acquired in tpm_tis_send */
373 tpm_tis_release_locality(dev, chip->locality);
374
375 return size;
376 }
377
tpm_tis_cleanup(struct udevice * dev)378 int tpm_tis_cleanup(struct udevice *dev)
379 {
380 struct tpm_chip *chip = dev_get_priv(dev);
381 int ret;
382
383 ret = tpm_tis_request_locality(dev, 0);
384 if (ret)
385 return ret;
386
387 tpm_tis_ready(dev);
388
389 tpm_tis_release_locality(dev, chip->locality);
390
391 return 0;
392 }
393
tpm_tis_open(struct udevice * dev)394 int tpm_tis_open(struct udevice *dev)
395 {
396 struct tpm_chip *chip = dev_get_priv(dev);
397 int ret;
398
399 if (chip->is_open)
400 return -EBUSY;
401
402 ret = tpm_tis_request_locality(dev, 0);
403 if (!ret)
404 chip->is_open = 1;
405
406 return ret;
407 }
408
tpm_tis_ops_register(struct udevice * dev,struct tpm_tis_phy_ops * ops)409 void tpm_tis_ops_register(struct udevice *dev, struct tpm_tis_phy_ops *ops)
410 {
411 struct tpm_chip *chip = dev_get_priv(dev);
412
413 chip->phy_ops = ops;
414 }
415
tis_check_ops(struct tpm_tis_phy_ops * phy_ops)416 static bool tis_check_ops(struct tpm_tis_phy_ops *phy_ops)
417 {
418 if (!phy_ops || !phy_ops->read_bytes || !phy_ops->write_bytes ||
419 !phy_ops->read32 || !phy_ops->write32)
420 return false;
421
422 return true;
423 }
424
tpm_tis_init(struct udevice * dev)425 int tpm_tis_init(struct udevice *dev)
426 {
427 struct tpm_chip *chip = dev_get_priv(dev);
428 struct tpm_tis_phy_ops *phy_ops = chip->phy_ops;
429 int ret;
430 u32 tmp;
431
432 if (!tis_check_ops(phy_ops)) {
433 log_err("Driver bug. No bus ops defined\n");
434 return -1;
435 }
436
437 chip->timeout_a = TIS_SHORT_TIMEOUT_MS;
438 chip->timeout_b = TIS_LONG_TIMEOUT_MS;
439 chip->timeout_c = TIS_SHORT_TIMEOUT_MS;
440 chip->timeout_d = TIS_SHORT_TIMEOUT_MS;
441
442 ret = tpm_tis_request_locality(dev, 0);
443 if (ret)
444 return ret;
445
446 /* Disable interrupts */
447 phy_ops->read32(dev, TPM_INT_ENABLE(chip->locality), &tmp);
448 tmp |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT |
449 TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT;
450 tmp &= ~TPM_GLOBAL_INT_ENABLE;
451 phy_ops->write32(dev, TPM_INT_ENABLE(chip->locality), tmp);
452
453 phy_ops->read_bytes(dev, TPM_RID(chip->locality), 1, &chip->rid);
454 phy_ops->read32(dev, TPM_DID_VID(chip->locality), &chip->vend_dev);
455
456 return tpm_tis_release_locality(dev, chip->locality);
457 }
458
tpm_tis_close(struct udevice * dev)459 int tpm_tis_close(struct udevice *dev)
460 {
461 struct tpm_chip *chip = dev_get_priv(dev);
462 int ret = 0;
463
464 if (chip->is_open) {
465 ret = tpm_tis_release_locality(dev, chip->locality);
466 chip->is_open = 0;
467 }
468
469 return ret;
470 }
471