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