3 * Device Driver for the Infineon Technologies
4 * SLD 9630 TT Trusted Platform Module
5 * Specifications at www.trustedcomputinggroup.org
7 * Copyright (C) 2005, Marcel Selhorst <selhorst@crypto.rub.de>
8 * Applied Data Security Group, Ruhr-University Bochum, Germany
9 * Project-Homepage: http://www.prosec.rub.de/tpm
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation, version 2 of the
20 /* Infineon specific definitions */
21 /* maximum number of WTX-packages */
22 #define TPM_MAX_WTX_PACKAGES 50
23 /* msleep-Time for WTX-packages */
24 #define TPM_WTX_MSLEEP_TIME 20
25 /* msleep-Time --> Interval to check status register */
26 #define TPM_MSLEEP_TIME 3
27 /* gives number of max. msleep()-calls before throwing timeout */
28 #define TPM_MAX_TRIES 5000
29 #define TCPA_INFINEON_DEV_VEN_VALUE 0x15D1
30 #define TPM_DATA (TPM_ADDR + 1) & 0xff
32 /* TPM header definitions */
33 enum infineon_tpm_header {
35 TPM_VL_CHANNEL_CONTROL = 0x07,
36 TPM_VL_CHANNEL_PERSONALISATION = 0x0A,
37 TPM_VL_CHANNEL_TPM = 0x0B,
38 TPM_VL_CONTROL = 0x00,
41 TPM_CTRL_WTX_ABORT = 0x18,
42 TPM_CTRL_WTX_ABORT_ACK = 0x18,
43 TPM_CTRL_ERROR = 0x20,
44 TPM_CTRL_CHAININGACK = 0x40,
45 TPM_CTRL_CHAINING = 0x80,
47 TPM_CTRL_DATA_CHA = 0x84,
48 TPM_CTRL_DATA_CHA_ACK = 0xC4
51 enum infineon_tpm_register {
58 enum infineon_tpm_command_bits {
65 enum infineon_tpm_status_bits {
74 /* some outgoing values */
75 enum infineon_tpm_values {
79 RESET_LP_IRQC_DISABLE = 0x41,
80 ENABLE_REGISTER_PAIR = 0x55,
83 DISABLE_REGISTER_PAIR = 0xAA,
90 static int number_of_wtx;
92 static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo)
99 for (i = 0; i < 4096; i++) {
100 status = inb(chip->vendor->base + WRFIFO);
101 if (status == 0xff) {
109 /* Note: The values which are currently in the FIFO of the TPM
110 are thrown away since there is no usage for them. Usually,
111 this has nothing to say, since the TPM will give its answer
112 immediately or will be aborted anyway, so the data here is
113 usually garbage and useless.
114 We have to clean this, because the next communication with
115 the TPM would be rubbish, if there is still some old data
120 status = inb(chip->vendor->base + RDFIFO);
121 status = inb(chip->vendor->base + STAT);
123 if (i == TPM_MAX_TRIES)
125 } while ((status & (1 << STAT_RDA)) != 0);
129 static int wait(struct tpm_chip *chip, int wait_for_bit)
133 for (i = 0; i < TPM_MAX_TRIES; i++) {
134 status = inb(chip->vendor->base + STAT);
135 /* check the status-register if wait_for_bit is set */
136 if (status & 1 << wait_for_bit)
138 msleep(TPM_MSLEEP_TIME);
140 if (i == TPM_MAX_TRIES) { /* timeout occurs */
141 if (wait_for_bit == STAT_XFE)
142 dev_err(&chip->pci_dev->dev,
143 "Timeout in wait(STAT_XFE)\n");
144 if (wait_for_bit == STAT_RDA)
145 dev_err(&chip->pci_dev->dev,
146 "Timeout in wait(STAT_RDA)\n");
152 static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
154 wait(chip, STAT_XFE);
155 outb(sendbyte, chip->vendor->base + WRFIFO);
158 /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more
159 calculation time, it sends a WTX-package, which has to be acknowledged
160 or aborted. This usually occurs if you are hammering the TPM with key
161 creation. Set the maximum number of WTX-packages in the definitions
162 above, if the number is reached, the waiting-time will be denied
163 and the TPM command has to be resend.
166 static void tpm_wtx(struct tpm_chip *chip)
169 dev_info(&chip->pci_dev->dev, "Granting WTX (%02d / %02d)\n",
170 number_of_wtx, TPM_MAX_WTX_PACKAGES);
171 wait_and_send(chip, TPM_VL_VER);
172 wait_and_send(chip, TPM_CTRL_WTX);
173 wait_and_send(chip, 0x00);
174 wait_and_send(chip, 0x00);
175 msleep(TPM_WTX_MSLEEP_TIME);
178 static void tpm_wtx_abort(struct tpm_chip *chip)
180 dev_info(&chip->pci_dev->dev, "Aborting WTX\n");
181 wait_and_send(chip, TPM_VL_VER);
182 wait_and_send(chip, TPM_CTRL_WTX_ABORT);
183 wait_and_send(chip, 0x00);
184 wait_and_send(chip, 0x00);
186 msleep(TPM_WTX_MSLEEP_TIME);
189 static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
196 /* start receiving header */
197 for (i = 0; i < 4; i++) {
198 ret = wait(chip, STAT_RDA);
201 buf[i] = inb(chip->vendor->base + RDFIFO);
204 if (buf[0] != TPM_VL_VER) {
205 dev_err(&chip->pci_dev->dev,
206 "Wrong transport protocol implementation!\n");
210 if (buf[1] == TPM_CTRL_DATA) {
211 /* size of the data received */
212 size = ((buf[2] << 8) | buf[3]);
214 for (i = 0; i < size; i++) {
215 wait(chip, STAT_RDA);
216 buf[i] = inb(chip->vendor->base + RDFIFO);
219 if ((size == 0x6D00) && (buf[1] == 0x80)) {
220 dev_err(&chip->pci_dev->dev,
221 "Error handling on vendor layer!\n");
225 for (i = 0; i < size; i++)
232 if (buf[1] == TPM_CTRL_WTX) {
233 dev_info(&chip->pci_dev->dev, "WTX-package received\n");
234 if (number_of_wtx < TPM_MAX_WTX_PACKAGES) {
243 if (buf[1] == TPM_CTRL_WTX_ABORT_ACK) {
244 dev_info(&chip->pci_dev->dev, "WTX-abort acknowledged\n");
248 if (buf[1] == TPM_CTRL_ERROR) {
249 dev_err(&chip->pci_dev->dev, "ERROR-package received:\n");
250 if (buf[4] == TPM_INF_NAK)
251 dev_err(&chip->pci_dev->dev,
252 "-> Negative acknowledgement"
253 " - retransmit command!\n");
259 static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count)
263 u8 count_high, count_low, count_4, count_3, count_2, count_1;
265 /* Disabling Reset, LP and IRQC */
266 outb(RESET_LP_IRQC_DISABLE, chip->vendor->base + CMD);
268 ret = empty_fifo(chip, 1);
270 dev_err(&chip->pci_dev->dev, "Timeout while clearing FIFO\n");
274 ret = wait(chip, STAT_XFE);
278 count_4 = (count & 0xff000000) >> 24;
279 count_3 = (count & 0x00ff0000) >> 16;
280 count_2 = (count & 0x0000ff00) >> 8;
281 count_1 = (count & 0x000000ff);
282 count_high = ((count + 6) & 0xffffff00) >> 8;
283 count_low = ((count + 6) & 0x000000ff);
286 wait_and_send(chip, TPM_VL_VER);
287 wait_and_send(chip, TPM_CTRL_DATA);
288 wait_and_send(chip, count_high);
289 wait_and_send(chip, count_low);
291 /* Sending Data Header */
292 wait_and_send(chip, TPM_VL_VER);
293 wait_and_send(chip, TPM_VL_CHANNEL_TPM);
294 wait_and_send(chip, count_4);
295 wait_and_send(chip, count_3);
296 wait_and_send(chip, count_2);
297 wait_and_send(chip, count_1);
300 for (i = 0; i < count; i++) {
301 wait_and_send(chip, buf[i]);
306 static void tpm_inf_cancel(struct tpm_chip *chip)
309 This has something to do with the internal functions
310 of the TPM. Abort isn't really necessary...
314 static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
315 static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
316 static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
317 static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
319 static struct attribute *inf_attrs[] = {
320 &dev_attr_pubek.attr,
323 &dev_attr_cancel.attr,
327 static struct attribute_group inf_attr_grp = {.attrs = inf_attrs };
329 static struct file_operations inf_ops = {
330 .owner = THIS_MODULE,
335 .release = tpm_release,
338 static struct tpm_vendor_specific tpm_inf = {
339 .recv = tpm_inf_recv,
340 .send = tpm_inf_send,
341 .cancel = tpm_inf_cancel,
342 .req_complete_mask = 0,
343 .req_complete_val = 0,
344 .attr_group = &inf_attr_grp,
345 .miscdev = {.fops = &inf_ops,},
348 static int __devinit tpm_inf_probe(struct pci_dev *pci_dev,
349 const struct pci_device_id *pci_id)
357 if (pci_enable_device(pci_dev))
360 dev_info(&pci_dev->dev, "LPC-bus found at 0x%x\n", pci_id->device);
362 /* query chip for its vendor, its version number a.s.o. */
363 outb(ENABLE_REGISTER_PAIR, TPM_ADDR);
364 outb(IDVENL, TPM_ADDR);
365 vendorid[1] = inb(TPM_DATA);
366 outb(IDVENH, TPM_ADDR);
367 vendorid[0] = inb(TPM_DATA);
368 outb(IDPDL, TPM_ADDR);
369 productid[1] = inb(TPM_DATA);
370 outb(IDPDH, TPM_ADDR);
371 productid[0] = inb(TPM_DATA);
372 outb(CHIP_ID1, TPM_ADDR);
373 version[1] = inb(TPM_DATA);
374 outb(CHIP_ID2, TPM_ADDR);
375 version[0] = inb(TPM_DATA);
377 if ((vendorid[0] << 8 | vendorid[1]) == (TCPA_INFINEON_DEV_VEN_VALUE)) {
379 /* read IO-ports from TPM */
380 outb(IOLIMH, TPM_ADDR);
382 outb(IOLIML, TPM_ADDR);
384 tpm_inf.base = (ioh << 8) | iol;
386 if (tpm_inf.base == 0) {
387 dev_err(&pci_dev->dev, "No IO-ports set!\n");
388 pci_disable_device(pci_dev);
392 /* activate register */
393 outb(TPM_DAR, TPM_ADDR);
394 outb(0x01, TPM_DATA);
395 outb(DISABLE_REGISTER_PAIR, TPM_ADDR);
397 /* disable RESET, LP and IRQC */
398 outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD);
400 /* Finally, we're done, print some infos */
401 dev_info(&pci_dev->dev, "TPM found: "
403 "chip version %02x%02x, "
404 "vendor id %x%x (Infineon), "
405 "product id %02x%02x"
408 version[0], version[1],
409 vendorid[0], vendorid[1],
410 productid[0], productid[1], ((productid[0] == 0)
413 " (SLD 9630 TT 1.1)" : "");
415 rc = tpm_register_hardware(pci_dev, &tpm_inf);
417 pci_disable_device(pci_dev);
422 dev_info(&pci_dev->dev, "No Infineon TPM found!\n");
423 pci_disable_device(pci_dev);
428 static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
429 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)},
430 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)},
431 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
432 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
433 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
434 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)},
435 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)},
436 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2)},
440 MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
442 static struct pci_driver inf_pci_driver = {
444 .id_table = tpm_pci_tbl,
445 .probe = tpm_inf_probe,
446 .remove = __devexit_p(tpm_remove),
447 .suspend = tpm_pm_suspend,
448 .resume = tpm_pm_resume,
451 static int __init init_inf(void)
453 return pci_register_driver(&inf_pci_driver);
456 static void __exit cleanup_inf(void)
458 pci_unregister_driver(&inf_pci_driver);
461 module_init(init_inf);
462 module_exit(cleanup_inf);
464 MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>");
465 MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT");
466 MODULE_VERSION("1.4");
467 MODULE_LICENSE("GPL");