tpm_infineon.c revision 397c718299d848ff305ecd955838a9bd32f1f881
1/*
2 * Description:
3 * Device Driver for the Infineon Technologies
4 * SLD 9630 TT 1.1 and SLB 9635 TT 1.2 Trusted Platform Module
5 * Specifications at www.trustedcomputinggroup.org
6 *
7 * Copyright (C) 2005, Marcel Selhorst <selhorst@crypto.rub.de>
8 * Sirrix AG - security technologies, http://www.sirrix.com and
9 * Applied Data Security Group, Ruhr-University Bochum, Germany
10 * Project-Homepage: http://www.prosec.rub.de/tpm
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation, version 2 of the
15 * License.
16 */
17
18#include <linux/init.h>
19#include <linux/pnp.h>
20#include "tpm.h"
21
22/* Infineon specific definitions */
23/* maximum number of WTX-packages */
24#define	TPM_MAX_WTX_PACKAGES 	50
25/* msleep-Time for WTX-packages */
26#define	TPM_WTX_MSLEEP_TIME 	20
27/* msleep-Time --> Interval to check status register */
28#define	TPM_MSLEEP_TIME 	3
29/* gives number of max. msleep()-calls before throwing timeout */
30#define	TPM_MAX_TRIES		5000
31#define	TPM_INFINEON_DEV_VEN_VALUE	0x15D1
32
33/* These values will be filled after PnP-call */
34static int TPM_INF_DATA;
35static int TPM_INF_ADDR;
36static int TPM_INF_BASE;
37static int TPM_INF_ADDR_LEN;
38static int TPM_INF_PORT_LEN;
39
40/* TPM header definitions */
41enum infineon_tpm_header {
42	TPM_VL_VER = 0x01,
43	TPM_VL_CHANNEL_CONTROL = 0x07,
44	TPM_VL_CHANNEL_PERSONALISATION = 0x0A,
45	TPM_VL_CHANNEL_TPM = 0x0B,
46	TPM_VL_CONTROL = 0x00,
47	TPM_INF_NAK = 0x15,
48	TPM_CTRL_WTX = 0x10,
49	TPM_CTRL_WTX_ABORT = 0x18,
50	TPM_CTRL_WTX_ABORT_ACK = 0x18,
51	TPM_CTRL_ERROR = 0x20,
52	TPM_CTRL_CHAININGACK = 0x40,
53	TPM_CTRL_CHAINING = 0x80,
54	TPM_CTRL_DATA = 0x04,
55	TPM_CTRL_DATA_CHA = 0x84,
56	TPM_CTRL_DATA_CHA_ACK = 0xC4
57};
58
59enum infineon_tpm_register {
60	WRFIFO = 0x00,
61	RDFIFO = 0x01,
62	STAT = 0x02,
63	CMD = 0x03
64};
65
66enum infineon_tpm_command_bits {
67	CMD_DIS = 0x00,
68	CMD_LP = 0x01,
69	CMD_RES = 0x02,
70	CMD_IRQC = 0x06
71};
72
73enum infineon_tpm_status_bits {
74	STAT_XFE = 0x00,
75	STAT_LPA = 0x01,
76	STAT_FOK = 0x02,
77	STAT_TOK = 0x03,
78	STAT_IRQA = 0x06,
79	STAT_RDA = 0x07
80};
81
82/* some outgoing values */
83enum infineon_tpm_values {
84	CHIP_ID1 = 0x20,
85	CHIP_ID2 = 0x21,
86	TPM_DAR = 0x30,
87	RESET_LP_IRQC_DISABLE = 0x41,
88	ENABLE_REGISTER_PAIR = 0x55,
89	IOLIMH = 0x60,
90	IOLIML = 0x61,
91	DISABLE_REGISTER_PAIR = 0xAA,
92	IDVENL = 0xF1,
93	IDVENH = 0xF2,
94	IDPDL = 0xF3,
95	IDPDH = 0xF4
96};
97
98static int number_of_wtx;
99
100static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo)
101{
102	int status;
103	int check = 0;
104	int i;
105
106	if (clear_wrfifo) {
107		for (i = 0; i < 4096; i++) {
108			status = inb(chip->vendor.base + WRFIFO);
109			if (status == 0xff) {
110				if (check == 5)
111					break;
112				else
113					check++;
114			}
115		}
116	}
117	/* Note: The values which are currently in the FIFO of the TPM
118	   are thrown away since there is no usage for them. Usually,
119	   this has nothing to say, since the TPM will give its answer
120	   immediately or will be aborted anyway, so the data here is
121	   usually garbage and useless.
122	   We have to clean this, because the next communication with
123	   the TPM would be rubbish, if there is still some old data
124	   in the Read FIFO.
125	 */
126	i = 0;
127	do {
128		status = inb(chip->vendor.base + RDFIFO);
129		status = inb(chip->vendor.base + STAT);
130		i++;
131		if (i == TPM_MAX_TRIES)
132			return -EIO;
133	} while ((status & (1 << STAT_RDA)) != 0);
134	return 0;
135}
136
137static int wait(struct tpm_chip *chip, int wait_for_bit)
138{
139	int status;
140	int i;
141	for (i = 0; i < TPM_MAX_TRIES; i++) {
142		status = inb(chip->vendor.base + STAT);
143		/* check the status-register if wait_for_bit is set */
144		if (status & 1 << wait_for_bit)
145			break;
146		msleep(TPM_MSLEEP_TIME);
147	}
148	if (i == TPM_MAX_TRIES) {	/* timeout occurs */
149		if (wait_for_bit == STAT_XFE)
150			dev_err(chip->dev, "Timeout in wait(STAT_XFE)\n");
151		if (wait_for_bit == STAT_RDA)
152			dev_err(chip->dev, "Timeout in wait(STAT_RDA)\n");
153		return -EIO;
154	}
155	return 0;
156};
157
158static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
159{
160	wait(chip, STAT_XFE);
161	outb(sendbyte, chip->vendor.base + WRFIFO);
162}
163
164    /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more
165       calculation time, it sends a WTX-package, which has to be acknowledged
166       or aborted. This usually occurs if you are hammering the TPM with key
167       creation. Set the maximum number of WTX-packages in the definitions
168       above, if the number is reached, the waiting-time will be denied
169       and the TPM command has to be resend.
170     */
171
172static void tpm_wtx(struct tpm_chip *chip)
173{
174	number_of_wtx++;
175	dev_info(chip->dev, "Granting WTX (%02d / %02d)\n",
176		 number_of_wtx, TPM_MAX_WTX_PACKAGES);
177	wait_and_send(chip, TPM_VL_VER);
178	wait_and_send(chip, TPM_CTRL_WTX);
179	wait_and_send(chip, 0x00);
180	wait_and_send(chip, 0x00);
181	msleep(TPM_WTX_MSLEEP_TIME);
182}
183
184static void tpm_wtx_abort(struct tpm_chip *chip)
185{
186	dev_info(chip->dev, "Aborting WTX\n");
187	wait_and_send(chip, TPM_VL_VER);
188	wait_and_send(chip, TPM_CTRL_WTX_ABORT);
189	wait_and_send(chip, 0x00);
190	wait_and_send(chip, 0x00);
191	number_of_wtx = 0;
192	msleep(TPM_WTX_MSLEEP_TIME);
193}
194
195static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
196{
197	int i;
198	int ret;
199	u32 size = 0;
200	number_of_wtx = 0;
201
202recv_begin:
203	/* start receiving header */
204	for (i = 0; i < 4; i++) {
205		ret = wait(chip, STAT_RDA);
206		if (ret)
207			return -EIO;
208		buf[i] = inb(chip->vendor.base + RDFIFO);
209	}
210
211	if (buf[0] != TPM_VL_VER) {
212		dev_err(chip->dev,
213			"Wrong transport protocol implementation!\n");
214		return -EIO;
215	}
216
217	if (buf[1] == TPM_CTRL_DATA) {
218		/* size of the data received */
219		size = ((buf[2] << 8) | buf[3]);
220
221		for (i = 0; i < size; i++) {
222			wait(chip, STAT_RDA);
223			buf[i] = inb(chip->vendor.base + RDFIFO);
224		}
225
226		if ((size == 0x6D00) && (buf[1] == 0x80)) {
227			dev_err(chip->dev, "Error handling on vendor layer!\n");
228			return -EIO;
229		}
230
231		for (i = 0; i < size; i++)
232			buf[i] = buf[i + 6];
233
234		size = size - 6;
235		return size;
236	}
237
238	if (buf[1] == TPM_CTRL_WTX) {
239		dev_info(chip->dev, "WTX-package received\n");
240		if (number_of_wtx < TPM_MAX_WTX_PACKAGES) {
241			tpm_wtx(chip);
242			goto recv_begin;
243		} else {
244			tpm_wtx_abort(chip);
245			goto recv_begin;
246		}
247	}
248
249	if (buf[1] == TPM_CTRL_WTX_ABORT_ACK) {
250		dev_info(chip->dev, "WTX-abort acknowledged\n");
251		return size;
252	}
253
254	if (buf[1] == TPM_CTRL_ERROR) {
255		dev_err(chip->dev, "ERROR-package received:\n");
256		if (buf[4] == TPM_INF_NAK)
257			dev_err(chip->dev,
258				"-> Negative acknowledgement"
259				" - retransmit command!\n");
260		return -EIO;
261	}
262	return -EIO;
263}
264
265static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count)
266{
267	int i;
268	int ret;
269	u8 count_high, count_low, count_4, count_3, count_2, count_1;
270
271	/* Disabling Reset, LP and IRQC */
272	outb(RESET_LP_IRQC_DISABLE, chip->vendor.base + CMD);
273
274	ret = empty_fifo(chip, 1);
275	if (ret) {
276		dev_err(chip->dev, "Timeout while clearing FIFO\n");
277		return -EIO;
278	}
279
280	ret = wait(chip, STAT_XFE);
281	if (ret)
282		return -EIO;
283
284	count_4 = (count & 0xff000000) >> 24;
285	count_3 = (count & 0x00ff0000) >> 16;
286	count_2 = (count & 0x0000ff00) >> 8;
287	count_1 = (count & 0x000000ff);
288	count_high = ((count + 6) & 0xffffff00) >> 8;
289	count_low = ((count + 6) & 0x000000ff);
290
291	/* Sending Header */
292	wait_and_send(chip, TPM_VL_VER);
293	wait_and_send(chip, TPM_CTRL_DATA);
294	wait_and_send(chip, count_high);
295	wait_and_send(chip, count_low);
296
297	/* Sending Data Header */
298	wait_and_send(chip, TPM_VL_VER);
299	wait_and_send(chip, TPM_VL_CHANNEL_TPM);
300	wait_and_send(chip, count_4);
301	wait_and_send(chip, count_3);
302	wait_and_send(chip, count_2);
303	wait_and_send(chip, count_1);
304
305	/* Sending Data */
306	for (i = 0; i < count; i++) {
307		wait_and_send(chip, buf[i]);
308	}
309	return count;
310}
311
312static void tpm_inf_cancel(struct tpm_chip *chip)
313{
314	/*
315	   Since we are using the legacy mode to communicate
316	   with the TPM, we have no cancel functions, but have
317	   a workaround for interrupting the TPM through WTX.
318	 */
319}
320
321static u8 tpm_inf_status(struct tpm_chip *chip)
322{
323	return inb(chip->vendor.base + STAT);
324}
325
326static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
327static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
328static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
329static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
330
331static struct attribute *inf_attrs[] = {
332	&dev_attr_pubek.attr,
333	&dev_attr_pcrs.attr,
334	&dev_attr_caps.attr,
335	&dev_attr_cancel.attr,
336	NULL,
337};
338
339static struct attribute_group inf_attr_grp = {.attrs = inf_attrs };
340
341static struct file_operations inf_ops = {
342	.owner = THIS_MODULE,
343	.llseek = no_llseek,
344	.open = tpm_open,
345	.read = tpm_read,
346	.write = tpm_write,
347	.release = tpm_release,
348};
349
350static const struct tpm_vendor_specific tpm_inf = {
351	.recv = tpm_inf_recv,
352	.send = tpm_inf_send,
353	.cancel = tpm_inf_cancel,
354	.status = tpm_inf_status,
355	.req_complete_mask = 0,
356	.req_complete_val = 0,
357	.attr_group = &inf_attr_grp,
358	.miscdev = {.fops = &inf_ops,},
359};
360
361static const struct pnp_device_id tpm_pnp_tbl[] = {
362	/* Infineon TPMs */
363	{"IFX0101", 0},
364	{"IFX0102", 0},
365	{"", 0}
366};
367
368MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl);
369
370static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
371				       const struct pnp_device_id *dev_id)
372{
373	int rc = 0;
374	u8 iol, ioh;
375	int vendorid[2];
376	int version[2];
377	int productid[2];
378	char chipname[20];
379	struct tpm_chip *chip;
380
381	/* read IO-ports through PnP */
382	if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
383	    !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) {
384		TPM_INF_ADDR = pnp_port_start(dev, 0);
385		TPM_INF_ADDR_LEN = pnp_port_len(dev, 0);
386		TPM_INF_DATA = (TPM_INF_ADDR + 1);
387		TPM_INF_BASE = pnp_port_start(dev, 1);
388		TPM_INF_PORT_LEN = pnp_port_len(dev, 1);
389		if ((TPM_INF_PORT_LEN < 4) || (TPM_INF_ADDR_LEN < 2)) {
390			rc = -EINVAL;
391			goto err_last;
392		}
393		dev_info(&dev->dev, "Found %s with ID %s\n",
394			 dev->name, dev_id->id);
395		if (!((TPM_INF_BASE >> 8) & 0xff)) {
396			rc = -EINVAL;
397			goto err_last;
398		}
399		/* publish my base address and request region */
400		if (request_region
401		    (TPM_INF_BASE, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) {
402			rc = -EINVAL;
403			goto err_last;
404		}
405		if (request_region
406		    (TPM_INF_ADDR, TPM_INF_ADDR_LEN, "tpm_infineon0") == NULL) {
407			rc = -EINVAL;
408			goto err_last;
409		}
410	} else {
411		rc = -EINVAL;
412		goto err_last;
413	}
414
415	/* query chip for its vendor, its version number a.s.o. */
416	outb(ENABLE_REGISTER_PAIR, TPM_INF_ADDR);
417	outb(IDVENL, TPM_INF_ADDR);
418	vendorid[1] = inb(TPM_INF_DATA);
419	outb(IDVENH, TPM_INF_ADDR);
420	vendorid[0] = inb(TPM_INF_DATA);
421	outb(IDPDL, TPM_INF_ADDR);
422	productid[1] = inb(TPM_INF_DATA);
423	outb(IDPDH, TPM_INF_ADDR);
424	productid[0] = inb(TPM_INF_DATA);
425	outb(CHIP_ID1, TPM_INF_ADDR);
426	version[1] = inb(TPM_INF_DATA);
427	outb(CHIP_ID2, TPM_INF_ADDR);
428	version[0] = inb(TPM_INF_DATA);
429
430	switch ((productid[0] << 8) | productid[1]) {
431	case 6:
432		snprintf(chipname, sizeof(chipname), " (SLD 9630 TT 1.1)");
433		break;
434	case 11:
435		snprintf(chipname, sizeof(chipname), " (SLB 9635 TT 1.2)");
436		break;
437	default:
438		snprintf(chipname, sizeof(chipname), " (unknown chip)");
439		break;
440	}
441
442	if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) {
443
444		/* configure TPM with IO-ports */
445		outb(IOLIMH, TPM_INF_ADDR);
446		outb(((TPM_INF_BASE >> 8) & 0xff), TPM_INF_DATA);
447		outb(IOLIML, TPM_INF_ADDR);
448		outb((TPM_INF_BASE & 0xff), TPM_INF_DATA);
449
450		/* control if IO-ports are set correctly */
451		outb(IOLIMH, TPM_INF_ADDR);
452		ioh = inb(TPM_INF_DATA);
453		outb(IOLIML, TPM_INF_ADDR);
454		iol = inb(TPM_INF_DATA);
455
456		if ((ioh << 8 | iol) != TPM_INF_BASE) {
457			dev_err(&dev->dev,
458				"Could not set IO-ports to 0x%x\n",
459				TPM_INF_BASE);
460			rc = -EIO;
461			goto err_release_region;
462		}
463
464		/* activate register */
465		outb(TPM_DAR, TPM_INF_ADDR);
466		outb(0x01, TPM_INF_DATA);
467		outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
468
469		/* disable RESET, LP and IRQC */
470		outb(RESET_LP_IRQC_DISABLE, TPM_INF_BASE + CMD);
471
472		/* Finally, we're done, print some infos */
473		dev_info(&dev->dev, "TPM found: "
474			 "config base 0x%x, "
475			 "io base 0x%x, "
476			 "chip version 0x%02x%02x, "
477			 "vendor id 0x%x%x (Infineon), "
478			 "product id 0x%02x%02x"
479			 "%s\n",
480			 TPM_INF_ADDR,
481			 TPM_INF_BASE,
482			 version[0], version[1],
483			 vendorid[0], vendorid[1],
484			 productid[0], productid[1], chipname);
485
486		if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) {
487			goto err_release_region;
488		}
489		chip->vendor.base = TPM_INF_BASE;
490		return 0;
491	} else {
492		rc = -ENODEV;
493		goto err_release_region;
494	}
495
496err_release_region:
497	release_region(TPM_INF_BASE, TPM_INF_PORT_LEN);
498	release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN);
499
500err_last:
501	return rc;
502}
503
504static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev)
505{
506	struct tpm_chip *chip = pnp_get_drvdata(dev);
507
508	if (chip) {
509		release_region(TPM_INF_BASE, TPM_INF_PORT_LEN);
510		release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN);
511		tpm_remove_hardware(chip->dev);
512	}
513}
514
515static struct pnp_driver tpm_inf_pnp = {
516	.name = "tpm_inf_pnp",
517	.driver = {
518		.owner = THIS_MODULE,
519		.suspend = tpm_pm_suspend,
520		.resume = tpm_pm_resume,
521	},
522	.id_table = tpm_pnp_tbl,
523	.probe = tpm_inf_pnp_probe,
524	.remove = __devexit_p(tpm_inf_pnp_remove),
525};
526
527static int __init init_inf(void)
528{
529	return pnp_register_driver(&tpm_inf_pnp);
530}
531
532static void __exit cleanup_inf(void)
533{
534	pnp_unregister_driver(&tpm_inf_pnp);
535}
536
537module_init(init_inf);
538module_exit(cleanup_inf);
539
540MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>");
541MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
542MODULE_VERSION("1.8");
543MODULE_LICENSE("GPL");
544