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