1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <linux/init.h>
19#include <linux/pnp.h>
20#include "tpm.h"
21
22
23
24#define TPM_MAX_WTX_PACKAGES 50
25
26#define TPM_WTX_MSLEEP_TIME 20
27
28#define TPM_MSLEEP_TIME 3
29
30#define TPM_MAX_TRIES 5000
31#define TPM_INFINEON_DEV_VEN_VALUE 0x15D1
32
33#define TPM_INF_IO_PORT 0x0
34#define TPM_INF_IO_MEM 0x1
35
36#define TPM_INF_ADDR 0x0
37#define TPM_INF_DATA 0x1
38
39struct tpm_inf_dev {
40 int iotype;
41
42 void __iomem *mem_base;
43 unsigned long map_base;
44 unsigned long map_size;
45 unsigned int index_off;
46
47 unsigned int data_regs;
48 unsigned int data_size;
49
50 unsigned int config_port;
51 unsigned int config_size;
52};
53
54static struct tpm_inf_dev tpm_dev;
55
56static inline void tpm_data_out(unsigned char data, unsigned char offset)
57{
58 if (tpm_dev.iotype == TPM_INF_IO_PORT)
59 outb(data, tpm_dev.data_regs + offset);
60 else
61 writeb(data, tpm_dev.mem_base + tpm_dev.data_regs + offset);
62}
63
64static inline unsigned char tpm_data_in(unsigned char offset)
65{
66 if (tpm_dev.iotype == TPM_INF_IO_PORT)
67 return inb(tpm_dev.data_regs + offset);
68 else
69 return readb(tpm_dev.mem_base + tpm_dev.data_regs + offset);
70}
71
72static inline void tpm_config_out(unsigned char data, unsigned char offset)
73{
74 if (tpm_dev.iotype == TPM_INF_IO_PORT)
75 outb(data, tpm_dev.config_port + offset);
76 else
77 writeb(data, tpm_dev.mem_base + tpm_dev.index_off + offset);
78}
79
80static inline unsigned char tpm_config_in(unsigned char offset)
81{
82 if (tpm_dev.iotype == TPM_INF_IO_PORT)
83 return inb(tpm_dev.config_port + offset);
84 else
85 return readb(tpm_dev.mem_base + tpm_dev.index_off + offset);
86}
87
88
89enum infineon_tpm_header {
90 TPM_VL_VER = 0x01,
91 TPM_VL_CHANNEL_CONTROL = 0x07,
92 TPM_VL_CHANNEL_PERSONALISATION = 0x0A,
93 TPM_VL_CHANNEL_TPM = 0x0B,
94 TPM_VL_CONTROL = 0x00,
95 TPM_INF_NAK = 0x15,
96 TPM_CTRL_WTX = 0x10,
97 TPM_CTRL_WTX_ABORT = 0x18,
98 TPM_CTRL_WTX_ABORT_ACK = 0x18,
99 TPM_CTRL_ERROR = 0x20,
100 TPM_CTRL_CHAININGACK = 0x40,
101 TPM_CTRL_CHAINING = 0x80,
102 TPM_CTRL_DATA = 0x04,
103 TPM_CTRL_DATA_CHA = 0x84,
104 TPM_CTRL_DATA_CHA_ACK = 0xC4
105};
106
107enum infineon_tpm_register {
108 WRFIFO = 0x00,
109 RDFIFO = 0x01,
110 STAT = 0x02,
111 CMD = 0x03
112};
113
114enum infineon_tpm_command_bits {
115 CMD_DIS = 0x00,
116 CMD_LP = 0x01,
117 CMD_RES = 0x02,
118 CMD_IRQC = 0x06
119};
120
121enum infineon_tpm_status_bits {
122 STAT_XFE = 0x00,
123 STAT_LPA = 0x01,
124 STAT_FOK = 0x02,
125 STAT_TOK = 0x03,
126 STAT_IRQA = 0x06,
127 STAT_RDA = 0x07
128};
129
130
131enum infineon_tpm_values {
132 CHIP_ID1 = 0x20,
133 CHIP_ID2 = 0x21,
134 TPM_DAR = 0x30,
135 RESET_LP_IRQC_DISABLE = 0x41,
136 ENABLE_REGISTER_PAIR = 0x55,
137 IOLIMH = 0x60,
138 IOLIML = 0x61,
139 DISABLE_REGISTER_PAIR = 0xAA,
140 IDVENL = 0xF1,
141 IDVENH = 0xF2,
142 IDPDL = 0xF3,
143 IDPDH = 0xF4
144};
145
146static int number_of_wtx;
147
148static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo)
149{
150 int status;
151 int check = 0;
152 int i;
153
154 if (clear_wrfifo) {
155 for (i = 0; i < 4096; i++) {
156 status = tpm_data_in(WRFIFO);
157 if (status == 0xff) {
158 if (check == 5)
159 break;
160 else
161 check++;
162 }
163 }
164 }
165
166
167
168
169
170
171
172
173
174 i = 0;
175 do {
176 status = tpm_data_in(RDFIFO);
177 status = tpm_data_in(STAT);
178 i++;
179 if (i == TPM_MAX_TRIES)
180 return -EIO;
181 } while ((status & (1 << STAT_RDA)) != 0);
182 return 0;
183}
184
185static int wait(struct tpm_chip *chip, int wait_for_bit)
186{
187 int status;
188 int i;
189 for (i = 0; i < TPM_MAX_TRIES; i++) {
190 status = tpm_data_in(STAT);
191
192 if (status & 1 << wait_for_bit)
193 break;
194 msleep(TPM_MSLEEP_TIME);
195 }
196 if (i == TPM_MAX_TRIES) {
197 if (wait_for_bit == STAT_XFE)
198 dev_err(chip->dev, "Timeout in wait(STAT_XFE)\n");
199 if (wait_for_bit == STAT_RDA)
200 dev_err(chip->dev, "Timeout in wait(STAT_RDA)\n");
201 return -EIO;
202 }
203 return 0;
204};
205
206static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
207{
208 wait(chip, STAT_XFE);
209 tpm_data_out(sendbyte, WRFIFO);
210}
211
212
213
214
215
216
217
218
219
220static void tpm_wtx(struct tpm_chip *chip)
221{
222 number_of_wtx++;
223 dev_info(chip->dev, "Granting WTX (%02d / %02d)\n",
224 number_of_wtx, TPM_MAX_WTX_PACKAGES);
225 wait_and_send(chip, TPM_VL_VER);
226 wait_and_send(chip, TPM_CTRL_WTX);
227 wait_and_send(chip, 0x00);
228 wait_and_send(chip, 0x00);
229 msleep(TPM_WTX_MSLEEP_TIME);
230}
231
232static void tpm_wtx_abort(struct tpm_chip *chip)
233{
234 dev_info(chip->dev, "Aborting WTX\n");
235 wait_and_send(chip, TPM_VL_VER);
236 wait_and_send(chip, TPM_CTRL_WTX_ABORT);
237 wait_and_send(chip, 0x00);
238 wait_and_send(chip, 0x00);
239 number_of_wtx = 0;
240 msleep(TPM_WTX_MSLEEP_TIME);
241}
242
243static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
244{
245 int i;
246 int ret;
247 u32 size = 0;
248 number_of_wtx = 0;
249
250recv_begin:
251
252 for (i = 0; i < 4; i++) {
253 ret = wait(chip, STAT_RDA);
254 if (ret)
255 return -EIO;
256 buf[i] = tpm_data_in(RDFIFO);
257 }
258
259 if (buf[0] != TPM_VL_VER) {
260 dev_err(chip->dev,
261 "Wrong transport protocol implementation!\n");
262 return -EIO;
263 }
264
265 if (buf[1] == TPM_CTRL_DATA) {
266
267 size = ((buf[2] << 8) | buf[3]);
268
269 for (i = 0; i < size; i++) {
270 wait(chip, STAT_RDA);
271 buf[i] = tpm_data_in(RDFIFO);
272 }
273
274 if ((size == 0x6D00) && (buf[1] == 0x80)) {
275 dev_err(chip->dev, "Error handling on vendor layer!\n");
276 return -EIO;
277 }
278
279 for (i = 0; i < size; i++)
280 buf[i] = buf[i + 6];
281
282 size = size - 6;
283 return size;
284 }
285
286 if (buf[1] == TPM_CTRL_WTX) {
287 dev_info(chip->dev, "WTX-package received\n");
288 if (number_of_wtx < TPM_MAX_WTX_PACKAGES) {
289 tpm_wtx(chip);
290 goto recv_begin;
291 } else {
292 tpm_wtx_abort(chip);
293 goto recv_begin;
294 }
295 }
296
297 if (buf[1] == TPM_CTRL_WTX_ABORT_ACK) {
298 dev_info(chip->dev, "WTX-abort acknowledged\n");
299 return size;
300 }
301
302 if (buf[1] == TPM_CTRL_ERROR) {
303 dev_err(chip->dev, "ERROR-package received:\n");
304 if (buf[4] == TPM_INF_NAK)
305 dev_err(chip->dev,
306 "-> Negative acknowledgement"
307 " - retransmit command!\n");
308 return -EIO;
309 }
310 return -EIO;
311}
312
313static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count)
314{
315 int i;
316 int ret;
317 u8 count_high, count_low, count_4, count_3, count_2, count_1;
318
319
320 tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
321
322 ret = empty_fifo(chip, 1);
323 if (ret) {
324 dev_err(chip->dev, "Timeout while clearing FIFO\n");
325 return -EIO;
326 }
327
328 ret = wait(chip, STAT_XFE);
329 if (ret)
330 return -EIO;
331
332 count_4 = (count & 0xff000000) >> 24;
333 count_3 = (count & 0x00ff0000) >> 16;
334 count_2 = (count & 0x0000ff00) >> 8;
335 count_1 = (count & 0x000000ff);
336 count_high = ((count + 6) & 0xffffff00) >> 8;
337 count_low = ((count + 6) & 0x000000ff);
338
339
340 wait_and_send(chip, TPM_VL_VER);
341 wait_and_send(chip, TPM_CTRL_DATA);
342 wait_and_send(chip, count_high);
343 wait_and_send(chip, count_low);
344
345
346 wait_and_send(chip, TPM_VL_VER);
347 wait_and_send(chip, TPM_VL_CHANNEL_TPM);
348 wait_and_send(chip, count_4);
349 wait_and_send(chip, count_3);
350 wait_and_send(chip, count_2);
351 wait_and_send(chip, count_1);
352
353
354 for (i = 0; i < count; i++) {
355 wait_and_send(chip, buf[i]);
356 }
357 return count;
358}
359
360static void tpm_inf_cancel(struct tpm_chip *chip)
361{
362
363
364
365
366
367}
368
369static u8 tpm_inf_status(struct tpm_chip *chip)
370{
371 return tpm_data_in(STAT);
372}
373
374static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
375static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
376static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
377static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
378
379static struct attribute *inf_attrs[] = {
380 &dev_attr_pubek.attr,
381 &dev_attr_pcrs.attr,
382 &dev_attr_caps.attr,
383 &dev_attr_cancel.attr,
384 NULL,
385};
386
387static struct attribute_group inf_attr_grp = {.attrs = inf_attrs };
388
389static const struct file_operations inf_ops = {
390 .owner = THIS_MODULE,
391 .llseek = no_llseek,
392 .open = tpm_open,
393 .read = tpm_read,
394 .write = tpm_write,
395 .release = tpm_release,
396};
397
398static const struct tpm_vendor_specific tpm_inf = {
399 .recv = tpm_inf_recv,
400 .send = tpm_inf_send,
401 .cancel = tpm_inf_cancel,
402 .status = tpm_inf_status,
403 .req_complete_mask = 0,
404 .req_complete_val = 0,
405 .attr_group = &inf_attr_grp,
406 .miscdev = {.fops = &inf_ops,},
407};
408
409static const struct pnp_device_id tpm_inf_pnp_tbl[] = {
410
411 {"IFX0101", 0},
412 {"IFX0102", 0},
413 {"", 0}
414};
415
416MODULE_DEVICE_TABLE(pnp, tpm_inf_pnp_tbl);
417
418static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
419 const struct pnp_device_id *dev_id)
420{
421 int rc = 0;
422 u8 iol, ioh;
423 int vendorid[2];
424 int version[2];
425 int productid[2];
426 char chipname[20];
427 struct tpm_chip *chip;
428
429
430 if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
431 !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) {
432
433 tpm_dev.iotype = TPM_INF_IO_PORT;
434
435 tpm_dev.config_port = pnp_port_start(dev, 0);
436 tpm_dev.config_size = pnp_port_len(dev, 0);
437 tpm_dev.data_regs = pnp_port_start(dev, 1);
438 tpm_dev.data_size = pnp_port_len(dev, 1);
439 if ((tpm_dev.data_size < 4) || (tpm_dev.config_size < 2)) {
440 rc = -EINVAL;
441 goto err_last;
442 }
443 dev_info(&dev->dev, "Found %s with ID %s\n",
444 dev->name, dev_id->id);
445 if (!((tpm_dev.data_regs >> 8) & 0xff)) {
446 rc = -EINVAL;
447 goto err_last;
448 }
449
450 if (request_region(tpm_dev.data_regs, tpm_dev.data_size,
451 "tpm_infineon0") == NULL) {
452 rc = -EINVAL;
453 goto err_last;
454 }
455 if (request_region(tpm_dev.config_port, tpm_dev.config_size,
456 "tpm_infineon0") == NULL) {
457 release_region(tpm_dev.data_regs, tpm_dev.data_size);
458 rc = -EINVAL;
459 goto err_last;
460 }
461 } else if (pnp_mem_valid(dev, 0) &&
462 !(pnp_mem_flags(dev, 0) & IORESOURCE_DISABLED)) {
463
464 tpm_dev.iotype = TPM_INF_IO_MEM;
465
466 tpm_dev.map_base = pnp_mem_start(dev, 0);
467 tpm_dev.map_size = pnp_mem_len(dev, 0);
468
469 dev_info(&dev->dev, "Found %s with ID %s\n",
470 dev->name, dev_id->id);
471
472
473 if (request_mem_region(tpm_dev.map_base, tpm_dev.map_size,
474 "tpm_infineon0") == NULL) {
475 rc = -EINVAL;
476 goto err_last;
477 }
478
479 tpm_dev.mem_base = ioremap(tpm_dev.map_base, tpm_dev.map_size);
480 if (tpm_dev.mem_base == NULL) {
481 release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
482 rc = -EINVAL;
483 goto err_last;
484 }
485
486
487
488
489
490
491
492
493 tpm_dev.index_off = TPM_ADDR;
494 tpm_dev.data_regs = 0x0;
495 } else {
496 rc = -EINVAL;
497 goto err_last;
498 }
499
500
501 tpm_config_out(ENABLE_REGISTER_PAIR, TPM_INF_ADDR);
502 tpm_config_out(IDVENL, TPM_INF_ADDR);
503 vendorid[1] = tpm_config_in(TPM_INF_DATA);
504 tpm_config_out(IDVENH, TPM_INF_ADDR);
505 vendorid[0] = tpm_config_in(TPM_INF_DATA);
506 tpm_config_out(IDPDL, TPM_INF_ADDR);
507 productid[1] = tpm_config_in(TPM_INF_DATA);
508 tpm_config_out(IDPDH, TPM_INF_ADDR);
509 productid[0] = tpm_config_in(TPM_INF_DATA);
510 tpm_config_out(CHIP_ID1, TPM_INF_ADDR);
511 version[1] = tpm_config_in(TPM_INF_DATA);
512 tpm_config_out(CHIP_ID2, TPM_INF_ADDR);
513 version[0] = tpm_config_in(TPM_INF_DATA);
514
515 switch ((productid[0] << 8) | productid[1]) {
516 case 6:
517 snprintf(chipname, sizeof(chipname), " (SLD 9630 TT 1.1)");
518 break;
519 case 11:
520 snprintf(chipname, sizeof(chipname), " (SLB 9635 TT 1.2)");
521 break;
522 default:
523 snprintf(chipname, sizeof(chipname), " (unknown chip)");
524 break;
525 }
526
527 if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) {
528
529
530 tpm_config_out(IOLIMH, TPM_INF_ADDR);
531 tpm_config_out((tpm_dev.data_regs >> 8) & 0xff, TPM_INF_DATA);
532 tpm_config_out(IOLIML, TPM_INF_ADDR);
533 tpm_config_out((tpm_dev.data_regs & 0xff), TPM_INF_DATA);
534
535
536 tpm_config_out(IOLIMH, TPM_INF_ADDR);
537 ioh = tpm_config_in(TPM_INF_DATA);
538 tpm_config_out(IOLIML, TPM_INF_ADDR);
539 iol = tpm_config_in(TPM_INF_DATA);
540
541 if ((ioh << 8 | iol) != tpm_dev.data_regs) {
542 dev_err(&dev->dev,
543 "Could not set IO-data registers to 0x%x\n",
544 tpm_dev.data_regs);
545 rc = -EIO;
546 goto err_release_region;
547 }
548
549
550 tpm_config_out(TPM_DAR, TPM_INF_ADDR);
551 tpm_config_out(0x01, TPM_INF_DATA);
552 tpm_config_out(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
553
554
555 tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
556
557
558 dev_info(&dev->dev, "TPM found: "
559 "config base 0x%lx, "
560 "data base 0x%lx, "
561 "chip version 0x%02x%02x, "
562 "vendor id 0x%x%x (Infineon), "
563 "product id 0x%02x%02x"
564 "%s\n",
565 tpm_dev.iotype == TPM_INF_IO_PORT ?
566 tpm_dev.config_port :
567 tpm_dev.map_base + tpm_dev.index_off,
568 tpm_dev.iotype == TPM_INF_IO_PORT ?
569 tpm_dev.data_regs :
570 tpm_dev.map_base + tpm_dev.data_regs,
571 version[0], version[1],
572 vendorid[0], vendorid[1],
573 productid[0], productid[1], chipname);
574
575 if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf)))
576 goto err_release_region;
577
578 return 0;
579 } else {
580 rc = -ENODEV;
581 goto err_release_region;
582 }
583
584err_release_region:
585 if (tpm_dev.iotype == TPM_INF_IO_PORT) {
586 release_region(tpm_dev.data_regs, tpm_dev.data_size);
587 release_region(tpm_dev.config_port, tpm_dev.config_size);
588 } else {
589 iounmap(tpm_dev.mem_base);
590 release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
591 }
592
593err_last:
594 return rc;
595}
596
597static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev)
598{
599 struct tpm_chip *chip = pnp_get_drvdata(dev);
600
601 if (chip) {
602 if (tpm_dev.iotype == TPM_INF_IO_PORT) {
603 release_region(tpm_dev.data_regs, tpm_dev.data_size);
604 release_region(tpm_dev.config_port,
605 tpm_dev.config_size);
606 } else {
607 iounmap(tpm_dev.mem_base);
608 release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
609 }
610 tpm_dev_vendor_release(chip);
611 tpm_remove_hardware(chip->dev);
612 }
613}
614
615static int tpm_inf_pnp_suspend(struct pnp_dev *dev, pm_message_t pm_state)
616{
617 struct tpm_chip *chip = pnp_get_drvdata(dev);
618 int rc;
619 if (chip) {
620 u8 savestate[] = {
621 0, 193,
622 0, 0, 0, 10,
623 0, 0, 0, 152
624 };
625 dev_info(&dev->dev, "saving TPM state\n");
626 rc = tpm_inf_send(chip, savestate, sizeof(savestate));
627 if (rc < 0) {
628 dev_err(&dev->dev, "error while saving TPM state\n");
629 return rc;
630 }
631 }
632 return 0;
633}
634
635static int tpm_inf_pnp_resume(struct pnp_dev *dev)
636{
637
638 tpm_config_out(ENABLE_REGISTER_PAIR, TPM_INF_ADDR);
639 tpm_config_out(IOLIMH, TPM_INF_ADDR);
640 tpm_config_out((tpm_dev.data_regs >> 8) & 0xff, TPM_INF_DATA);
641 tpm_config_out(IOLIML, TPM_INF_ADDR);
642 tpm_config_out((tpm_dev.data_regs & 0xff), TPM_INF_DATA);
643
644 tpm_config_out(TPM_DAR, TPM_INF_ADDR);
645 tpm_config_out(0x01, TPM_INF_DATA);
646 tpm_config_out(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
647
648 tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
649 return tpm_pm_resume(&dev->dev);
650}
651
652static struct pnp_driver tpm_inf_pnp_driver = {
653 .name = "tpm_inf_pnp",
654 .id_table = tpm_inf_pnp_tbl,
655 .probe = tpm_inf_pnp_probe,
656 .suspend = tpm_inf_pnp_suspend,
657 .resume = tpm_inf_pnp_resume,
658 .remove = __devexit_p(tpm_inf_pnp_remove)
659};
660
661static int __init init_inf(void)
662{
663 return pnp_register_driver(&tpm_inf_pnp_driver);
664}
665
666static void __exit cleanup_inf(void)
667{
668 pnp_unregister_driver(&tpm_inf_pnp_driver);
669}
670
671module_init(init_inf);
672module_exit(cleanup_inf);
673
674MODULE_AUTHOR("Marcel Selhorst <tpmdd@sirrix.com>");
675MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
676MODULE_VERSION("1.9.2");
677MODULE_LICENSE("GPL");
678