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