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