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->pdev, "Timeout in wait(STAT_XFE)\n");
199 if (wait_for_bit == STAT_RDA)
200 dev_err(chip->pdev, "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->pdev, "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->pdev, "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->pdev,
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->pdev, "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->pdev, "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->pdev, "WTX-abort acknowledged\n");
299 return size;
300 }
301
302 if (buf[1] == TPM_CTRL_ERROR) {
303 dev_err(chip->pdev, "ERROR-package received:\n");
304 if (buf[4] == TPM_INF_NAK)
305 dev_err(chip->pdev,
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->pdev, "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 const struct tpm_class_ops tpm_inf = {
375 .recv = tpm_inf_recv,
376 .send = tpm_inf_send,
377 .cancel = tpm_inf_cancel,
378 .status = tpm_inf_status,
379 .req_complete_mask = 0,
380 .req_complete_val = 0,
381};
382
383static const struct pnp_device_id tpm_inf_pnp_tbl[] = {
384
385 {"IFX0101", 0},
386 {"IFX0102", 0},
387 {"", 0}
388};
389
390MODULE_DEVICE_TABLE(pnp, tpm_inf_pnp_tbl);
391
392static int tpm_inf_pnp_probe(struct pnp_dev *dev,
393 const struct pnp_device_id *dev_id)
394{
395 int rc = 0;
396 u8 iol, ioh;
397 int vendorid[2];
398 int version[2];
399 int productid[2];
400 char chipname[20];
401 struct tpm_chip *chip;
402
403
404 if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
405 !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) {
406
407 tpm_dev.iotype = TPM_INF_IO_PORT;
408
409 tpm_dev.config_port = pnp_port_start(dev, 0);
410 tpm_dev.config_size = pnp_port_len(dev, 0);
411 tpm_dev.data_regs = pnp_port_start(dev, 1);
412 tpm_dev.data_size = pnp_port_len(dev, 1);
413 if ((tpm_dev.data_size < 4) || (tpm_dev.config_size < 2)) {
414 rc = -EINVAL;
415 goto err_last;
416 }
417 dev_info(&dev->dev, "Found %s with ID %s\n",
418 dev->name, dev_id->id);
419 if (!((tpm_dev.data_regs >> 8) & 0xff)) {
420 rc = -EINVAL;
421 goto err_last;
422 }
423
424 if (request_region(tpm_dev.data_regs, tpm_dev.data_size,
425 "tpm_infineon0") == NULL) {
426 rc = -EINVAL;
427 goto err_last;
428 }
429 if (request_region(tpm_dev.config_port, tpm_dev.config_size,
430 "tpm_infineon0") == NULL) {
431 release_region(tpm_dev.data_regs, tpm_dev.data_size);
432 rc = -EINVAL;
433 goto err_last;
434 }
435 } else if (pnp_mem_valid(dev, 0) &&
436 !(pnp_mem_flags(dev, 0) & IORESOURCE_DISABLED)) {
437
438 tpm_dev.iotype = TPM_INF_IO_MEM;
439
440 tpm_dev.map_base = pnp_mem_start(dev, 0);
441 tpm_dev.map_size = pnp_mem_len(dev, 0);
442
443 dev_info(&dev->dev, "Found %s with ID %s\n",
444 dev->name, dev_id->id);
445
446
447 if (request_mem_region(tpm_dev.map_base, tpm_dev.map_size,
448 "tpm_infineon0") == NULL) {
449 rc = -EINVAL;
450 goto err_last;
451 }
452
453 tpm_dev.mem_base = ioremap(tpm_dev.map_base, tpm_dev.map_size);
454 if (tpm_dev.mem_base == NULL) {
455 release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
456 rc = -EINVAL;
457 goto err_last;
458 }
459
460
461
462
463
464
465
466
467 tpm_dev.index_off = TPM_ADDR;
468 tpm_dev.data_regs = 0x0;
469 } else {
470 rc = -EINVAL;
471 goto err_last;
472 }
473
474
475 tpm_config_out(ENABLE_REGISTER_PAIR, TPM_INF_ADDR);
476 tpm_config_out(IDVENL, TPM_INF_ADDR);
477 vendorid[1] = tpm_config_in(TPM_INF_DATA);
478 tpm_config_out(IDVENH, TPM_INF_ADDR);
479 vendorid[0] = tpm_config_in(TPM_INF_DATA);
480 tpm_config_out(IDPDL, TPM_INF_ADDR);
481 productid[1] = tpm_config_in(TPM_INF_DATA);
482 tpm_config_out(IDPDH, TPM_INF_ADDR);
483 productid[0] = tpm_config_in(TPM_INF_DATA);
484 tpm_config_out(CHIP_ID1, TPM_INF_ADDR);
485 version[1] = tpm_config_in(TPM_INF_DATA);
486 tpm_config_out(CHIP_ID2, TPM_INF_ADDR);
487 version[0] = tpm_config_in(TPM_INF_DATA);
488
489 switch ((productid[0] << 8) | productid[1]) {
490 case 6:
491 snprintf(chipname, sizeof(chipname), " (SLD 9630 TT 1.1)");
492 break;
493 case 11:
494 snprintf(chipname, sizeof(chipname), " (SLB 9635 TT 1.2)");
495 break;
496 default:
497 snprintf(chipname, sizeof(chipname), " (unknown chip)");
498 break;
499 }
500
501 if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) {
502
503
504 tpm_config_out(IOLIMH, TPM_INF_ADDR);
505 tpm_config_out((tpm_dev.data_regs >> 8) & 0xff, TPM_INF_DATA);
506 tpm_config_out(IOLIML, TPM_INF_ADDR);
507 tpm_config_out((tpm_dev.data_regs & 0xff), TPM_INF_DATA);
508
509
510 tpm_config_out(IOLIMH, TPM_INF_ADDR);
511 ioh = tpm_config_in(TPM_INF_DATA);
512 tpm_config_out(IOLIML, TPM_INF_ADDR);
513 iol = tpm_config_in(TPM_INF_DATA);
514
515 if ((ioh << 8 | iol) != tpm_dev.data_regs) {
516 dev_err(&dev->dev,
517 "Could not set IO-data registers to 0x%x\n",
518 tpm_dev.data_regs);
519 rc = -EIO;
520 goto err_release_region;
521 }
522
523
524 tpm_config_out(TPM_DAR, TPM_INF_ADDR);
525 tpm_config_out(0x01, TPM_INF_DATA);
526 tpm_config_out(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
527
528
529 tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
530
531
532 dev_info(&dev->dev, "TPM found: "
533 "config base 0x%lx, "
534 "data base 0x%lx, "
535 "chip version 0x%02x%02x, "
536 "vendor id 0x%x%x (Infineon), "
537 "product id 0x%02x%02x"
538 "%s\n",
539 tpm_dev.iotype == TPM_INF_IO_PORT ?
540 tpm_dev.config_port :
541 tpm_dev.map_base + tpm_dev.index_off,
542 tpm_dev.iotype == TPM_INF_IO_PORT ?
543 tpm_dev.data_regs :
544 tpm_dev.map_base + tpm_dev.data_regs,
545 version[0], version[1],
546 vendorid[0], vendorid[1],
547 productid[0], productid[1], chipname);
548
549 chip = tpmm_chip_alloc(&dev->dev, &tpm_inf);
550 if (IS_ERR(chip)) {
551 rc = PTR_ERR(chip);
552 goto err_release_region;
553 }
554
555 rc = tpm_chip_register(chip);
556 if (rc)
557 goto err_release_region;
558
559 return 0;
560 } else {
561 rc = -ENODEV;
562 goto err_release_region;
563 }
564
565err_release_region:
566 if (tpm_dev.iotype == TPM_INF_IO_PORT) {
567 release_region(tpm_dev.data_regs, tpm_dev.data_size);
568 release_region(tpm_dev.config_port, tpm_dev.config_size);
569 } else {
570 iounmap(tpm_dev.mem_base);
571 release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
572 }
573
574err_last:
575 return rc;
576}
577
578static void tpm_inf_pnp_remove(struct pnp_dev *dev)
579{
580 struct tpm_chip *chip = pnp_get_drvdata(dev);
581
582 tpm_chip_unregister(chip);
583
584 if (tpm_dev.iotype == TPM_INF_IO_PORT) {
585 release_region(tpm_dev.data_regs, tpm_dev.data_size);
586 release_region(tpm_dev.config_port,
587 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}
593
594#ifdef CONFIG_PM_SLEEP
595static int tpm_inf_resume(struct device *dev)
596{
597
598 tpm_config_out(ENABLE_REGISTER_PAIR, TPM_INF_ADDR);
599 tpm_config_out(IOLIMH, TPM_INF_ADDR);
600 tpm_config_out((tpm_dev.data_regs >> 8) & 0xff, TPM_INF_DATA);
601 tpm_config_out(IOLIML, TPM_INF_ADDR);
602 tpm_config_out((tpm_dev.data_regs & 0xff), TPM_INF_DATA);
603
604 tpm_config_out(TPM_DAR, TPM_INF_ADDR);
605 tpm_config_out(0x01, TPM_INF_DATA);
606 tpm_config_out(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
607
608 tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
609 return tpm_pm_resume(dev);
610}
611#endif
612static SIMPLE_DEV_PM_OPS(tpm_inf_pm, tpm_pm_suspend, tpm_inf_resume);
613
614static struct pnp_driver tpm_inf_pnp_driver = {
615 .name = "tpm_inf_pnp",
616 .id_table = tpm_inf_pnp_tbl,
617 .probe = tpm_inf_pnp_probe,
618 .remove = tpm_inf_pnp_remove,
619 .driver = {
620 .pm = &tpm_inf_pm,
621 }
622};
623
624module_pnp_driver(tpm_inf_pnp_driver);
625
626MODULE_AUTHOR("Marcel Selhorst <tpmdd@sirrix.com>");
627MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
628MODULE_VERSION("1.9.2");
629MODULE_LICENSE("GPL");
630