1 /* Copyright 2013-2016 IBM Corp.
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 * implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <timebase.h>
18 #include <skiboot.h>
19 #include <device.h>
20 #include <i2c.h>
21 #include "../status_codes.h"
22 #include "../tpm_chip.h"
23 #include "tpm_i2c_interface.h"
24 #include "tpm_i2c_nuvoton.h"
25 #include <opal-api.h>
26
27 //#define DBG(fmt, ...) prlog(PR_DEBUG, fmt, ##__VA_ARGS__)
28 #define DBG(fmt, ...)
29
30 #define DRIVER_NAME "i2c_tpm_nuvoton"
31
32 /*
33 * Timings between various states or transitions within the interface protocol
34 * as defined in the TCG PC Client Platform TPM Profile specification, Revision
35 * 00.43.
36 */
37 #define TPM_TIMEOUT_A 750
38 #define TPM_TIMEOUT_B 2000
39 #define TPM_TIMEOUT_D 30
40
41 /* I2C interface offsets */
42 #define TPM_STS 0x00
43 #define TPM_BURST_COUNT 0x01
44 #define TPM_DATA_FIFO_W 0x20
45 #define TPM_DATA_FIFO_R 0x40
46
47 /* Bit masks for the TPM STATUS register */
48 #define TPM_STS_VALID 0x80
49 #define TPM_STS_COMMAND_READY 0x40
50 #define TPM_STS_GO 0x20
51 #define TPM_STS_DATA_AVAIL 0x10
52 #define TPM_STS_EXPECT 0x08
53
54
55 /* TPM Driver values */
56 #define MAX_STSVALID_POLLS 5
57 #define TPM_TIMEOUT_INTERVAL 10
58
59 static struct tpm_dev *tpm_device = NULL;
60
tpm_status_write_byte(uint8_t byte)61 static int tpm_status_write_byte(uint8_t byte)
62 {
63 uint8_t value = byte;
64 return tpm_i2c_request_send(tpm_device->bus_id, tpm_device->xscom_base,
65 SMBUS_WRITE, TPM_STS, 1, &value,
66 sizeof(value));
67 }
68
tpm_status_read_byte(uint8_t offset,uint8_t * byte)69 static int tpm_status_read_byte(uint8_t offset, uint8_t *byte)
70 {
71 return tpm_i2c_request_send(tpm_device->bus_id, tpm_device->xscom_base,
72 SMBUS_READ, offset, 1, byte,
73 sizeof(uint8_t));
74 }
75
tpm_check_status(uint8_t status,uint8_t mask,uint8_t expected)76 static bool tpm_check_status(uint8_t status, uint8_t mask, uint8_t expected)
77 {
78 return ((status & mask) == expected);
79 }
80
tpm_wait_for_command_ready(void)81 static int tpm_wait_for_command_ready(void)
82 {
83 uint64_t start, stop, now;
84 int rc;
85 uint8_t status;
86
87 start = mftb();
88 stop = start + msecs_to_tb(TPM_TIMEOUT_B);
89
90 do {
91 now = mftb();
92 rc = tpm_status_read_byte(TPM_STS, &status);
93 if (rc < 0) {
94 /**
95 * @fwts-label TPMReadCmdReady
96 * @fwts-advice Either the tpm device or the tpm-i2c
97 * interface doesn't seem to be working properly. Check
98 * the return code (rc) for further details.
99 */
100 prlog(PR_ERR, "NUVOTON: fail to read sts.commandReady, "
101 "rc=%d\n", rc);
102 return STB_DRIVER_ERROR;
103 }
104 if (tpm_check_status(status,
105 TPM_STS_COMMAND_READY,
106 TPM_STS_COMMAND_READY)) {
107 DBG("--- Command ready, delay=%lu/%d\n",
108 tb_to_msecs(now-start), TPM_TIMEOUT_B);
109 return 0;
110 }
111 if (tb_compare(now, stop) == TB_ABEFOREB)
112 time_wait_ms(TPM_TIMEOUT_INTERVAL);
113 else
114 break;
115 } while (1);
116
117 return STB_TPM_TIMEOUT;
118 }
119
tpm_set_command_ready(void)120 static int tpm_set_command_ready(void)
121 {
122 int rc, retries;
123 /*
124 * The first write to command ready may just abort an
125 * outstanding command, so we poll twice
126 */
127 for (retries = 0; retries < 2; retries++) {
128 rc = tpm_status_write_byte(TPM_STS_COMMAND_READY);
129 if (rc < 0) {
130 /**
131 * @fwts-label TPMWriteCmdReady
132 * @fwts-advice Either the tpm device or the tpm-i2c
133 * interface doesn't seem to be working properly. Check
134 * the return code (rc) for further details.
135 */
136 prlog(PR_ERR, "NUVOTON: fail to write sts.commandReady, "
137 "rc=%d\n", rc);
138 return STB_DRIVER_ERROR;
139 }
140 rc = tpm_wait_for_command_ready();
141 if (rc == STB_TPM_TIMEOUT)
142 continue;
143 return rc;
144 }
145 /**
146 * @fwts-label TPMCmdReadyTimeout
147 * @fwts-advice The command ready bit of the tpm status register is
148 * taking longer to be settled. Either the wait time need to be
149 * increased or the TPM device is not functional.
150 */
151 prlog(PR_ERR, "NUVOTON: timeout on sts.commandReady, delay > %d\n",
152 2*TPM_TIMEOUT_B);
153 return STB_TPM_TIMEOUT;
154 }
155
tpm_wait_for_fifo_status(uint8_t mask,uint8_t expected)156 static int tpm_wait_for_fifo_status(uint8_t mask, uint8_t expected)
157 {
158 int retries, rc;
159 uint8_t status;
160
161 for(retries = 0; retries <= MAX_STSVALID_POLLS; retries++) {
162 rc = tpm_status_read_byte(TPM_STS, &status);
163 if (rc < 0) {
164 /**
165 * @fwts-label TPMReadFifoStatus
166 * @fwts-advice Either the tpm device or the tpm-i2c
167 * interface doesn't seem to be working properly. Check
168 * the return code (rc) for further details.
169 */
170 prlog(PR_ERR, "NUVOTON: fail to read fifo status: "
171 "mask %x, expected %x, rc=%d\n", mask, expected,
172 rc);
173 return STB_DRIVER_ERROR;
174 }
175 if (tpm_check_status(status, mask, expected))
176 return 0;
177 /* Wait TPM STS register be settled */
178 time_wait_ms(5);
179 }
180 return STB_TPM_TIMEOUT;
181 }
182
tpm_wait_for_data_avail(void)183 static int tpm_wait_for_data_avail(void)
184 {
185 uint64_t start, stop, now;
186 uint8_t status;
187 int rc;
188
189 start = mftb();
190 stop = start + msecs_to_tb(TPM_TIMEOUT_A);
191
192 do {
193 now = mftb();
194 rc = tpm_status_read_byte(TPM_STS, &status);
195 if (rc < 0) {
196 /**
197 * @fwts-label TPMReadDataAvail
198 * @fwts-advice Either the tpm device or the tpm-i2c
199 * interface doesn't seem to be working properly. Check
200 * the return code (rc) for further details.
201 */
202 prlog(PR_ERR, "NUVOTON: fail to read sts.dataAvail, "
203 "rc=%d\n", rc);
204 return STB_DRIVER_ERROR;
205 }
206 if (tpm_check_status(status,
207 TPM_STS_VALID | TPM_STS_DATA_AVAIL,
208 TPM_STS_VALID | TPM_STS_DATA_AVAIL)) {
209 DBG("---- Data available. delay=%lu/%d\n",
210 tb_to_msecs(now-start), TPM_TIMEOUT_A);
211 return 0;
212 }
213 if (tb_compare(now, stop) == TB_ABEFOREB)
214 time_wait_ms(TPM_TIMEOUT_INTERVAL);
215 else
216 break;
217 } while (1);
218 /**
219 * @fwts-label TPMDataAvailBitTimeout
220 * @fwts-advice The data avail bit of the tpm status register is taking
221 * longer to be settled. Either the wait time need to be increased or
222 * the TPM device is not functional.
223 */
224 prlog(PR_ERR, "NUVOTON: timeout on sts.dataAvail, delay=%lu/%d\n",
225 tb_to_msecs(now-start), TPM_TIMEOUT_A);
226 return STB_TPM_TIMEOUT;
227 }
228
tpm_read_burst_count(void)229 static int tpm_read_burst_count(void)
230 {
231 uint64_t start, stop, now;
232 uint8_t burst_count;
233 int rc;
234
235 start = mftb();
236 stop = start + msecs_to_tb(TPM_TIMEOUT_D);
237 burst_count = 0;
238
239 do {
240 now = mftb();
241 /* In i2C, burstCount is 1 byte */
242 rc = tpm_status_read_byte(TPM_BURST_COUNT, &burst_count);
243 if (rc == 0 && burst_count > 0) {
244 DBG("---- burst_count=%d, delay=%lu/%d\n", burst_count,
245 tb_to_msecs(now-start), TPM_TIMEOUT_D);
246 return (int) burst_count;
247 }
248 if (rc < 0) {
249 /**
250 * @fwts-label TPMReadBurstCount
251 * @fwts-advice Either the tpm device or the tpm-i2c
252 * interface doesn't seem to be working properly. Check
253 * the return code (rc) for further details.
254 */
255 prlog(PR_ERR, "NUVOTON: fail to read sts.burstCount, "
256 "rc=%d\n", rc);
257 return STB_DRIVER_ERROR;
258 }
259 if (tb_compare(now, stop) == TB_ABEFOREB)
260 time_wait_ms(TPM_TIMEOUT_INTERVAL);
261 else
262 break;
263 } while (1);
264
265 /**
266 * @fwts-label TPMBurstCountTimeout
267 * @fwts-advice The burstcount bit of the tpm status register is
268 * taking longer to be settled. Either the wait time need to be
269 * increased or the TPM device is not functional.
270 */
271 prlog(PR_ERR, "NUVOTON: timeout on sts.burstCount, delay=%lu/%d\n",
272 tb_to_msecs(now-start), TPM_TIMEOUT_D);
273 return STB_TPM_TIMEOUT;
274 }
275
tpm_write_fifo(uint8_t * buf,size_t buflen)276 static int tpm_write_fifo(uint8_t* buf, size_t buflen)
277 {
278 int rc, burst_count;
279 size_t count, bytes;
280
281 /*
282 * We will transfer the command except for the last byte
283 * that will be transfered separately to allow for
284 * overflow checking
285 */
286 count = 0;
287 do {
288 burst_count = tpm_read_burst_count();
289 if (burst_count < 0)
290 return burst_count;
291
292 bytes = (count + burst_count > buflen - 1 ?
293 (buflen - 1 - count) : burst_count);
294
295 rc = tpm_i2c_request_send(tpm_device->bus_id,
296 tpm_device->xscom_base,
297 SMBUS_WRITE, TPM_DATA_FIFO_W,
298 1, &buf[count], bytes);
299 count += bytes;
300 DBG("%s FIFO: %zd bytes written, count=%zd, rc=%d\n",
301 (rc) ? "!!!!" : "----", bytes, count, rc);
302 if (rc < 0) {
303 /**
304 * @fwts-label TPMWriteFifo
305 * @fwts-advice Either the tpm device or the tpm-i2c
306 * interface doesn't seem to be working properly. Check
307 * the return code (rc) for further details.
308 */
309 prlog(PR_ERR, "NUVOTON: fail to write fifo, "
310 "count=%zd, rc=%d\n", count, rc);
311 return STB_DRIVER_ERROR;
312 }
313
314 rc = tpm_wait_for_fifo_status(TPM_STS_VALID | TPM_STS_EXPECT,
315 TPM_STS_VALID | TPM_STS_EXPECT);
316 if (rc == STB_DRIVER_ERROR)
317 return rc;
318 if (rc == STB_TPM_TIMEOUT) {
319 /**
320 * @fwts-label TPMWriteFifoNotExpecting
321 * @fwts-advice The write to the TPM FIFO overflowed,
322 * the TPM is not expecting more data. This indicates a
323 * bug in the TPM device driver.
324 */
325 prlog(PR_ERR, "NUVOTON: write FIFO overflow, not expecting "
326 "more data\n");
327 return STB_TPM_OVERFLOW;
328 }
329 } while (count < buflen - 1);
330
331 /*
332 * Write the last byte
333 */
334 burst_count = tpm_read_burst_count();
335 if (burst_count < 0)
336 return burst_count;
337
338 rc = tpm_i2c_request_send(tpm_device->bus_id,
339 tpm_device->xscom_base,
340 SMBUS_WRITE,
341 TPM_DATA_FIFO_W, 1,
342 &buf[count], 1);
343 count++;
344 DBG("%s FIFO: last byte written, count=%zd, rc=%d\n",
345 (rc) ? "!!!!" : "----", count, rc);
346
347 if (rc < 0) {
348 /**
349 * @fwts-label TPMWriteFifoLastByte
350 * @fwts-advice Either the tpm device or the tpm-i2c interface
351 * doesn't seem to be working properly. Check the return code
352 * (rc) for further details.
353 */
354 prlog(PR_ERR, "NUVOTON: fail to write fifo (last byte), "
355 "count=%zd, rc=%d\n", count, rc);
356 return STB_DRIVER_ERROR;
357 }
358 rc = tpm_wait_for_fifo_status(TPM_STS_VALID | TPM_STS_EXPECT,
359 TPM_STS_VALID | TPM_STS_EXPECT);
360 if (rc == STB_DRIVER_ERROR)
361 return rc;
362 if (rc == 0) {
363 /**
364 * @fwts-label TPMWriteFifoExpecting
365 * @fwts-advice The write to the TPM FIFO overflowed.
366 * It is expecting more data even though we think we
367 * are done. This indicates a bug in the TPM device
368 * driver.
369 */
370 prlog(PR_ERR, "TPM: write FIFO overflow, expecting "
371 "more data\n");
372 return STB_TPM_OVERFLOW;
373 }
374 return 0;
375 }
376
tpm_read_fifo(uint8_t * buf,size_t * buflen)377 static int tpm_read_fifo(uint8_t* buf, size_t* buflen)
378 {
379 int rc, burst_count;
380 size_t count;
381
382 rc = tpm_wait_for_data_avail();
383 if (rc < 0)
384 goto error;
385
386 count = 0;
387 do {
388 burst_count = tpm_read_burst_count();
389 if (burst_count < 0) {
390 rc = burst_count;
391 goto error;
392 }
393 if (count + burst_count > *buflen) {
394 /**
395 * @fwts-label TPMReadFifoOverflow
396 * @fwts-advice The read from TPM FIFO overflowed. It is
397 * expecting more data even though we think we are done.
398 * This indicates a bug in the TPM device driver.
399 */
400 prlog(PR_ERR, "NUVOTON: overflow on fifo read, c=%zd, "
401 "bc=%d, bl=%zd\n", count, burst_count, *buflen);
402 rc = STB_TPM_OVERFLOW;
403 }
404 rc = tpm_i2c_request_send(tpm_device->bus_id,
405 tpm_device->xscom_base,
406 SMBUS_READ,
407 TPM_DATA_FIFO_R, 1,
408 &buf[count], burst_count);
409 count += burst_count;
410 DBG("%s FIFO: %d bytes read, count=%zd, rc=%d\n",
411 (rc) ? "!!!!" : "----", burst_count, count, rc);
412 if (rc < 0) {
413 /**
414 * @fwts-label TPMReadFifo
415 * @fwts-advice Either the tpm device or the tpm-i2c interface
416 * doesn't seem to be working properly. Check the return code
417 * (rc) for further details.
418 */
419 prlog(PR_ERR, "NUVOTON: fail to read fifo, count=%zd, "
420 "rc=%d\n", count, rc);
421 rc = STB_DRIVER_ERROR;
422 goto error;
423 }
424 rc = tpm_wait_for_fifo_status(
425 TPM_STS_VALID | TPM_STS_DATA_AVAIL,
426 TPM_STS_VALID | TPM_STS_DATA_AVAIL);
427 if (rc == STB_DRIVER_ERROR)
428 goto error;
429 } while (rc == 0);
430
431 *buflen = count;
432 return 0;
433
434 error:
435 *buflen = 0;
436 return rc;
437 }
438
tpm_transmit(struct tpm_dev * dev,uint8_t * buf,size_t cmdlen,size_t * buflen)439 static int tpm_transmit(struct tpm_dev *dev, uint8_t* buf, size_t cmdlen,
440 size_t* buflen)
441 {
442 int rc = 0;
443 if (!dev) {
444 /**
445 * @fwts-label TPMDeviceNotInitialized
446 * @fwts-advice TPM device is not initialized. This indicates a
447 * bug in the tpm_transmit() caller
448 */
449 prlog(PR_ERR, "TPM: tpm device not initialized\n");
450 return STB_ARG_ERROR;
451 }
452 tpm_device = dev;
453 DBG("**** %s: dev %#x/%#x buf %016llx cmdlen %zu"
454 " buflen %zu ****\n",
455 __func__, dev->bus_id, dev->xscom_base, *(uint64_t*) buf,
456 cmdlen, *buflen);
457
458 DBG("step 1/5: set command ready\n");
459 rc = tpm_set_command_ready();
460 if (rc < 0)
461 goto out;
462
463 DBG("step 2/5: write FIFO\n");
464 rc = tpm_write_fifo(buf, cmdlen);
465 if (rc < 0)
466 goto out;
467
468 DBG("step 3/5: write sts.go\n");
469 rc = tpm_status_write_byte(TPM_STS_GO);
470 if (rc < 0) {
471 /**
472 * @fwts-label TPMWriteGo
473 * @fwts-advice Either the tpm device or the tpm-i2c interface
474 * doesn't seem to be working properly. Check the return code
475 * (rc) for further details.
476 */
477 prlog(PR_ERR, "NUVOTON: fail to write sts.go, rc=%d\n", rc);
478 rc = STB_DRIVER_ERROR;
479 goto out;
480 }
481
482 DBG("step 4/5: read FIFO\n");
483 rc = tpm_read_fifo(buf, buflen);
484 if (rc < 0)
485 goto out;
486
487 DBG("step 5/5: release tpm\n");
488 rc = tpm_status_write_byte(TPM_STS_COMMAND_READY);
489 if (rc < 0) {
490 /**
491 * @fwts-label TPMReleaseTpm
492 * @fwts-advice Either the tpm device or the tpm-i2c interface
493 * doesn't seem to be working properly. Check the return code
494 * (rc) for further details.
495 */
496 prlog(PR_ERR, "NUVOTON: fail to release tpm, rc=%d\n", rc);
497 rc = STB_DRIVER_ERROR;
498 }
499
500 out:
501 DBG("**** tpm_transmit %s, rc=%d ****\n",
502 (rc) ? "ERROR" : "SUCCESS", rc);
503 return rc;
504 }
505
506 static struct tpm_driver tpm_i2c_nuvoton_driver = {
507 .name = DRIVER_NAME,
508 .transmit = tpm_transmit,
509 };
510
nuvoton_tpm_quirk(void * data,struct i2c_request * req,int * rc)511 static int nuvoton_tpm_quirk(void *data, struct i2c_request *req, int *rc)
512 {
513 struct tpm_dev *tpm_device = data;
514
515 /* If we're doing i2cdetect on the TPM, pretent we just NACKed
516 * it due to errata in nuvoton firmware where if we let this
517 * request go through, it would steal the bus and you'd end up
518 * in a nice world of pain.
519 */
520 if (tpm_device->bus_id == req->bus->opal_id &&
521 tpm_device->xscom_base == req->dev_addr &&
522 ((req->op == I2C_READ && req->rw_len == 1) ||
523 (req->op == I2C_WRITE && req->rw_len == 0))) {
524 *rc = OPAL_I2C_TIMEOUT;
525 prlog(PR_DEBUG,"NUVOTON: Squashed i2c probe to avoid locking "
526 "I2C bus\n");
527 return 1;
528 }
529
530 return 0;
531 }
532
tpm_i2c_nuvoton_probe(void)533 void tpm_i2c_nuvoton_probe(void)
534 {
535 struct tpm_dev *tpm_device = NULL;
536 struct dt_node *node = NULL;
537 struct i2c_bus *bus;
538
539 dt_for_each_compatible(dt_root, node, "nuvoton,npct650") {
540 if (!dt_node_is_enabled(node))
541 continue;
542 tpm_device = (struct tpm_dev*) malloc(sizeof(struct tpm_dev));
543 assert(tpm_device);
544 /*
545 * Read TPM device address and bus id. Make sure the properties
546 * really exist if the default value is returned.
547 */
548 tpm_device->xscom_base = dt_prop_get_u32_def(node, "reg", 0);
549 if (!tpm_device->xscom_base &&
550 !dt_find_property(node, "reg")) {
551 /*
552 * @fwts-label NuvotonRegNotFound
553 * @fwts-advice reg property not found. This indicates
554 * a Hostboot bug if the property really doesn't exist
555 * in the tpm node.
556 */
557 prlog(PR_ERR, "NUVOTON: reg property not found, "
558 "tpm node %p\n", node);
559 goto disable;
560 }
561 tpm_device->bus_id = dt_prop_get_u32_def(node->parent,
562 "ibm,opal-id", 0);
563 if (!tpm_device->bus_id &&
564 !dt_find_property(node->parent, "ibm,opal-id")) {
565 /*
566 * @fwts-label NuvotonIbmOpalIdNotFound
567 * @fwts-advice ibm,opal-id property not found. This
568 * indicates a Hostboot bug if the property really
569 * doesn't exist in the tpm node.
570 */
571 prlog(PR_ERR, "NUVOTON: ibm,opal-id property not "
572 "found, tpm node parent %p\n", node->parent);
573 goto disable;
574 }
575 if (tpm_register_chip(node, tpm_device,
576 &tpm_i2c_nuvoton_driver)) {
577 free(tpm_device);
578 continue;
579 }
580 bus = i2c_find_bus_by_id(tpm_device->bus_id);
581 assert(bus->check_quirk == NULL);
582 bus->check_quirk = nuvoton_tpm_quirk;
583 bus->check_quirk_data = tpm_device;
584 }
585 return;
586 disable:
587 dt_add_property_string(node, "status", "disabled");
588 prlog(PR_NOTICE, "TPM: tpm node %p disabled\n", node);
589 free(tpm_device);
590 }
591