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