tpm: Pull everything related to /dev/tpmX into tpm-dev.c
[linux-2.6-block.git] / drivers / char / tpm / tpm_infineon.c
CommitLineData
ebb81fdb
MS
1/*
2 * Description:
3 * Device Driver for the Infineon Technologies
f9abb020 4 * SLD 9630 TT 1.1 and SLB 9635 TT 1.2 Trusted Platform Module
ebb81fdb
MS
5 * Specifications at www.trustedcomputinggroup.org
6 *
cbb2d5e4
RA
7 * Copyright (C) 2005, Marcel Selhorst <tpmdd@selhorst.net>
8 * Sirrix AG - security technologies <tpmdd@sirrix.com> and
ebb81fdb 9 * Applied Data Security Group, Ruhr-University Bochum, Germany
631dd1a8 10 * Project-Homepage: http://www.trust.rub.de/projects/linux-device-driver-infineon-tpm/
ebb81fdb
MS
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.
ebb81fdb
MS
16 */
17
397c7182 18#include <linux/init.h>
f9abb020 19#include <linux/pnp.h>
ebb81fdb
MS
20#include "tpm.h"
21
22/* Infineon specific definitions */
23/* maximum number of WTX-packages */
24#define TPM_MAX_WTX_PACKAGES 50
25/* msleep-Time for WTX-packages */
26#define TPM_WTX_MSLEEP_TIME 20
27/* msleep-Time --> Interval to check status register */
28#define TPM_MSLEEP_TIME 3
29/* gives number of max. msleep()-calls before throwing timeout */
30#define TPM_MAX_TRIES 5000
f9abb020
MS
31#define TPM_INFINEON_DEV_VEN_VALUE 0x15D1
32
d954e8ed
AW
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
93716b94
MS
42 void __iomem *mem_base; /* MMIO ioremap'd addr */
43 unsigned long map_base; /* phys MMIO base */
44 unsigned long map_size; /* MMIO region size */
45 unsigned int index_off; /* index register offset */
d954e8ed 46
93716b94 47 unsigned int data_regs; /* Data registers */
d954e8ed
AW
48 unsigned int data_size;
49
50 unsigned int config_port; /* IO Port config index reg */
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}
ebb81fdb
MS
87
88/* TPM header definitions */
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/* some outgoing values */
131enum infineon_tpm_values {
132 CHIP_ID1 = 0x20,
133 CHIP_ID2 = 0x21,
3dcce8e2 134 TPM_DAR = 0x30,
ebb81fdb
MS
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++) {
d954e8ed 156 status = tpm_data_in(WRFIFO);
ebb81fdb
MS
157 if (status == 0xff) {
158 if (check == 5)
159 break;
160 else
161 check++;
162 }
163 }
164 }
165 /* Note: The values which are currently in the FIFO of the TPM
166 are thrown away since there is no usage for them. Usually,
167 this has nothing to say, since the TPM will give its answer
168 immediately or will be aborted anyway, so the data here is
169 usually garbage and useless.
170 We have to clean this, because the next communication with
171 the TPM would be rubbish, if there is still some old data
172 in the Read FIFO.
173 */
174 i = 0;
175 do {
d954e8ed
AW
176 status = tpm_data_in(RDFIFO);
177 status = tpm_data_in(STAT);
ebb81fdb
MS
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++) {
d954e8ed 190 status = tpm_data_in(STAT);
ebb81fdb
MS
191 /* check the status-register if wait_for_bit is set */
192 if (status & 1 << wait_for_bit)
193 break;
194 msleep(TPM_MSLEEP_TIME);
195 }
196 if (i == TPM_MAX_TRIES) { /* timeout occurs */
197 if (wait_for_bit == STAT_XFE)
1b8333b0 198 dev_err(chip->dev, "Timeout in wait(STAT_XFE)\n");
ebb81fdb 199 if (wait_for_bit == STAT_RDA)
1b8333b0 200 dev_err(chip->dev, "Timeout in wait(STAT_RDA)\n");
ebb81fdb
MS
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);
d954e8ed 209 tpm_data_out(sendbyte, WRFIFO);
ebb81fdb
MS
210}
211
212 /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more
213 calculation time, it sends a WTX-package, which has to be acknowledged
214 or aborted. This usually occurs if you are hammering the TPM with key
215 creation. Set the maximum number of WTX-packages in the definitions
216 above, if the number is reached, the waiting-time will be denied
217 and the TPM command has to be resend.
218 */
219
220static void tpm_wtx(struct tpm_chip *chip)
221{
222 number_of_wtx++;
e659a3fe 223 dev_info(chip->dev, "Granting WTX (%02d / %02d)\n",
ebb81fdb
MS
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{
e659a3fe 234 dev_info(chip->dev, "Aborting WTX\n");
ebb81fdb
MS
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;
8c9e8779 248 number_of_wtx = 0;
ebb81fdb
MS
249
250recv_begin:
251 /* start receiving header */
252 for (i = 0; i < 4; i++) {
253 ret = wait(chip, STAT_RDA);
254 if (ret)
255 return -EIO;
d954e8ed 256 buf[i] = tpm_data_in(RDFIFO);
ebb81fdb
MS
257 }
258
259 if (buf[0] != TPM_VL_VER) {
e659a3fe 260 dev_err(chip->dev,
ebb81fdb
MS
261 "Wrong transport protocol implementation!\n");
262 return -EIO;
263 }
264
265 if (buf[1] == TPM_CTRL_DATA) {
266 /* size of the data received */
267 size = ((buf[2] << 8) | buf[3]);
268
269 for (i = 0; i < size; i++) {
270 wait(chip, STAT_RDA);
d954e8ed 271 buf[i] = tpm_data_in(RDFIFO);
ebb81fdb
MS
272 }
273
274 if ((size == 0x6D00) && (buf[1] == 0x80)) {
1b8333b0 275 dev_err(chip->dev, "Error handling on vendor layer!\n");
ebb81fdb
MS
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) {
e659a3fe 287 dev_info(chip->dev, "WTX-package received\n");
ebb81fdb
MS
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) {
e659a3fe 298 dev_info(chip->dev, "WTX-abort acknowledged\n");
ebb81fdb
MS
299 return size;
300 }
301
302 if (buf[1] == TPM_CTRL_ERROR) {
e659a3fe 303 dev_err(chip->dev, "ERROR-package received:\n");
ebb81fdb 304 if (buf[4] == TPM_INF_NAK)
e659a3fe 305 dev_err(chip->dev,
ebb81fdb
MS
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 /* Disabling Reset, LP and IRQC */
d954e8ed 320 tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
ebb81fdb
MS
321
322 ret = empty_fifo(chip, 1);
323 if (ret) {
e659a3fe 324 dev_err(chip->dev, "Timeout while clearing FIFO\n");
ebb81fdb
MS
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 /* Sending Header */
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 /* Sending Data Header */
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 /* Sending Data */
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{
f9abb020
MS
362 /*
363 Since we are using the legacy mode to communicate
364 with the TPM, we have no cancel functions, but have
365 a workaround for interrupting the TPM through WTX.
ebb81fdb
MS
366 */
367}
368
b4ed3e3c
KJH
369static u8 tpm_inf_status(struct tpm_chip *chip)
370{
d954e8ed 371 return tpm_data_in(STAT);
b4ed3e3c
KJH
372}
373
ebb81fdb
MS
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
e496f540 389static const struct tpm_vendor_specific tpm_inf = {
ebb81fdb
MS
390 .recv = tpm_inf_recv,
391 .send = tpm_inf_send,
392 .cancel = tpm_inf_cancel,
b4ed3e3c 393 .status = tpm_inf_status,
ebb81fdb
MS
394 .req_complete_mask = 0,
395 .req_complete_val = 0,
396 .attr_group = &inf_attr_grp,
ebb81fdb
MS
397};
398
93716b94 399static const struct pnp_device_id tpm_inf_pnp_tbl[] = {
f9abb020
MS
400 /* Infineon TPMs */
401 {"IFX0101", 0},
402 {"IFX0102", 0},
403 {"", 0}
404};
1b8333b0 405
93716b94 406MODULE_DEVICE_TABLE(pnp, tpm_inf_pnp_tbl);
f9abb020 407
afc6d369 408static int tpm_inf_pnp_probe(struct pnp_dev *dev,
1b8333b0 409 const struct pnp_device_id *dev_id)
ebb81fdb
MS
410{
411 int rc = 0;
412 u8 iol, ioh;
413 int vendorid[2];
414 int version[2];
415 int productid[2];
f9abb020 416 char chipname[20];
e496f540 417 struct tpm_chip *chip;
ebb81fdb 418
1b8333b0
MS
419 /* read IO-ports through PnP */
420 if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
421 !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) {
d954e8ed 422
93716b94 423 tpm_dev.iotype = TPM_INF_IO_PORT;
d954e8ed
AW
424
425 tpm_dev.config_port = pnp_port_start(dev, 0);
426 tpm_dev.config_size = pnp_port_len(dev, 0);
427 tpm_dev.data_regs = pnp_port_start(dev, 1);
428 tpm_dev.data_size = pnp_port_len(dev, 1);
429 if ((tpm_dev.data_size < 4) || (tpm_dev.config_size < 2)) {
8c9e8779
MS
430 rc = -EINVAL;
431 goto err_last;
432 }
1b8333b0
MS
433 dev_info(&dev->dev, "Found %s with ID %s\n",
434 dev->name, dev_id->id);
d954e8ed 435 if (!((tpm_dev.data_regs >> 8) & 0xff)) {
8c9e8779
MS
436 rc = -EINVAL;
437 goto err_last;
438 }
1b8333b0 439 /* publish my base address and request region */
d954e8ed
AW
440 if (request_region(tpm_dev.data_regs, tpm_dev.data_size,
441 "tpm_infineon0") == NULL) {
8c9e8779
MS
442 rc = -EINVAL;
443 goto err_last;
444 }
d954e8ed
AW
445 if (request_region(tpm_dev.config_port, tpm_dev.config_size,
446 "tpm_infineon0") == NULL) {
447 release_region(tpm_dev.data_regs, tpm_dev.data_size);
8c9e8779
MS
448 rc = -EINVAL;
449 goto err_last;
1b8333b0 450 }
d954e8ed 451 } else if (pnp_mem_valid(dev, 0) &&
93716b94 452 !(pnp_mem_flags(dev, 0) & IORESOURCE_DISABLED)) {
d954e8ed 453
93716b94 454 tpm_dev.iotype = TPM_INF_IO_MEM;
d954e8ed
AW
455
456 tpm_dev.map_base = pnp_mem_start(dev, 0);
457 tpm_dev.map_size = pnp_mem_len(dev, 0);
458
459 dev_info(&dev->dev, "Found %s with ID %s\n",
460 dev->name, dev_id->id);
461
462 /* publish my base address and request region */
463 if (request_mem_region(tpm_dev.map_base, tpm_dev.map_size,
464 "tpm_infineon0") == NULL) {
465 rc = -EINVAL;
466 goto err_last;
467 }
468
469 tpm_dev.mem_base = ioremap(tpm_dev.map_base, tpm_dev.map_size);
470 if (tpm_dev.mem_base == NULL) {
471 release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
472 rc = -EINVAL;
473 goto err_last;
474 }
475
476 /*
477 * The only known MMIO based Infineon TPM system provides
478 * a single large mem region with the device config
479 * registers at the default TPM_ADDR. The data registers
480 * seem like they could be placed anywhere within the MMIO
481 * region, but lets just put them at zero offset.
482 */
483 tpm_dev.index_off = TPM_ADDR;
484 tpm_dev.data_regs = 0x0;
e8a65015 485 } else {
8c9e8779
MS
486 rc = -EINVAL;
487 goto err_last;
f9abb020
MS
488 }
489
ebb81fdb 490 /* query chip for its vendor, its version number a.s.o. */
d954e8ed
AW
491 tpm_config_out(ENABLE_REGISTER_PAIR, TPM_INF_ADDR);
492 tpm_config_out(IDVENL, TPM_INF_ADDR);
493 vendorid[1] = tpm_config_in(TPM_INF_DATA);
494 tpm_config_out(IDVENH, TPM_INF_ADDR);
495 vendorid[0] = tpm_config_in(TPM_INF_DATA);
496 tpm_config_out(IDPDL, TPM_INF_ADDR);
497 productid[1] = tpm_config_in(TPM_INF_DATA);
498 tpm_config_out(IDPDH, TPM_INF_ADDR);
499 productid[0] = tpm_config_in(TPM_INF_DATA);
500 tpm_config_out(CHIP_ID1, TPM_INF_ADDR);
501 version[1] = tpm_config_in(TPM_INF_DATA);
502 tpm_config_out(CHIP_ID2, TPM_INF_ADDR);
503 version[0] = tpm_config_in(TPM_INF_DATA);
f9abb020
MS
504
505 switch ((productid[0] << 8) | productid[1]) {
506 case 6:
e8a65015 507 snprintf(chipname, sizeof(chipname), " (SLD 9630 TT 1.1)");
f9abb020
MS
508 break;
509 case 11:
e8a65015 510 snprintf(chipname, sizeof(chipname), " (SLB 9635 TT 1.2)");
f9abb020
MS
511 break;
512 default:
e8a65015 513 snprintf(chipname, sizeof(chipname), " (unknown chip)");
f9abb020
MS
514 break;
515 }
f9abb020
MS
516
517 if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) {
ebb81fdb 518
f9abb020 519 /* configure TPM with IO-ports */
d954e8ed
AW
520 tpm_config_out(IOLIMH, TPM_INF_ADDR);
521 tpm_config_out((tpm_dev.data_regs >> 8) & 0xff, TPM_INF_DATA);
522 tpm_config_out(IOLIML, TPM_INF_ADDR);
523 tpm_config_out((tpm_dev.data_regs & 0xff), TPM_INF_DATA);
f9abb020
MS
524
525 /* control if IO-ports are set correctly */
d954e8ed
AW
526 tpm_config_out(IOLIMH, TPM_INF_ADDR);
527 ioh = tpm_config_in(TPM_INF_DATA);
528 tpm_config_out(IOLIML, TPM_INF_ADDR);
529 iol = tpm_config_in(TPM_INF_DATA);
f9abb020 530
d954e8ed 531 if ((ioh << 8 | iol) != tpm_dev.data_regs) {
1b8333b0 532 dev_err(&dev->dev,
d954e8ed
AW
533 "Could not set IO-data registers to 0x%x\n",
534 tpm_dev.data_regs);
8c9e8779
MS
535 rc = -EIO;
536 goto err_release_region;
ebb81fdb
MS
537 }
538
539 /* activate register */
d954e8ed
AW
540 tpm_config_out(TPM_DAR, TPM_INF_ADDR);
541 tpm_config_out(0x01, TPM_INF_DATA);
542 tpm_config_out(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
ebb81fdb
MS
543
544 /* disable RESET, LP and IRQC */
d954e8ed 545 tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
ebb81fdb
MS
546
547 /* Finally, we're done, print some infos */
1b8333b0 548 dev_info(&dev->dev, "TPM found: "
d954e8ed
AW
549 "config base 0x%lx, "
550 "data base 0x%lx, "
e496f540
MS
551 "chip version 0x%02x%02x, "
552 "vendor id 0x%x%x (Infineon), "
553 "product id 0x%02x%02x"
ebb81fdb 554 "%s\n",
d954e8ed 555 tpm_dev.iotype == TPM_INF_IO_PORT ?
93716b94
MS
556 tpm_dev.config_port :
557 tpm_dev.map_base + tpm_dev.index_off,
d954e8ed 558 tpm_dev.iotype == TPM_INF_IO_PORT ?
93716b94
MS
559 tpm_dev.data_regs :
560 tpm_dev.map_base + tpm_dev.data_regs,
ebb81fdb
MS
561 version[0], version[1],
562 vendorid[0], vendorid[1],
f9abb020 563 productid[0], productid[1], chipname);
ebb81fdb 564
d954e8ed 565 if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf)))
8c9e8779 566 goto err_release_region;
d954e8ed 567
ebb81fdb
MS
568 return 0;
569 } else {
8c9e8779
MS
570 rc = -ENODEV;
571 goto err_release_region;
ebb81fdb 572 }
8c9e8779
MS
573
574err_release_region:
d954e8ed
AW
575 if (tpm_dev.iotype == TPM_INF_IO_PORT) {
576 release_region(tpm_dev.data_regs, tpm_dev.data_size);
577 release_region(tpm_dev.config_port, tpm_dev.config_size);
578 } else {
579 iounmap(tpm_dev.mem_base);
580 release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
581 }
8c9e8779
MS
582
583err_last:
584 return rc;
ebb81fdb
MS
585}
586
39af33fc 587static void tpm_inf_pnp_remove(struct pnp_dev *dev)
e659a3fe 588{
1b8333b0 589 struct tpm_chip *chip = pnp_get_drvdata(dev);
e659a3fe 590
1b8333b0 591 if (chip) {
d954e8ed
AW
592 if (tpm_dev.iotype == TPM_INF_IO_PORT) {
593 release_region(tpm_dev.data_regs, tpm_dev.data_size);
594 release_region(tpm_dev.config_port,
595 tpm_dev.config_size);
596 } else {
597 iounmap(tpm_dev.mem_base);
598 release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
599 }
93716b94 600 tpm_dev_vendor_release(chip);
e659a3fe 601 tpm_remove_hardware(chip->dev);
1b8333b0 602 }
e659a3fe
KJH
603}
604
93716b94
MS
605static int tpm_inf_pnp_suspend(struct pnp_dev *dev, pm_message_t pm_state)
606{
607 struct tpm_chip *chip = pnp_get_drvdata(dev);
608 int rc;
609 if (chip) {
610 u8 savestate[] = {
611 0, 193, /* TPM_TAG_RQU_COMMAND */
612 0, 0, 0, 10, /* blob length (in bytes) */
613 0, 0, 0, 152 /* TPM_ORD_SaveState */
614 };
615 dev_info(&dev->dev, "saving TPM state\n");
616 rc = tpm_inf_send(chip, savestate, sizeof(savestate));
617 if (rc < 0) {
618 dev_err(&dev->dev, "error while saving TPM state\n");
619 return rc;
620 }
621 }
622 return 0;
623}
624
625static int tpm_inf_pnp_resume(struct pnp_dev *dev)
626{
627 /* Re-configure TPM after suspending */
628 tpm_config_out(ENABLE_REGISTER_PAIR, TPM_INF_ADDR);
629 tpm_config_out(IOLIMH, TPM_INF_ADDR);
630 tpm_config_out((tpm_dev.data_regs >> 8) & 0xff, TPM_INF_DATA);
631 tpm_config_out(IOLIML, TPM_INF_ADDR);
632 tpm_config_out((tpm_dev.data_regs & 0xff), TPM_INF_DATA);
633 /* activate register */
634 tpm_config_out(TPM_DAR, TPM_INF_ADDR);
635 tpm_config_out(0x01, TPM_INF_DATA);
636 tpm_config_out(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
637 /* disable RESET, LP and IRQC */
638 tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
639 return tpm_pm_resume(&dev->dev);
640}
641
e1d42c98 642static struct pnp_driver tpm_inf_pnp_driver = {
1b8333b0 643 .name = "tpm_inf_pnp",
93716b94 644 .id_table = tpm_inf_pnp_tbl,
1b8333b0 645 .probe = tpm_inf_pnp_probe,
93716b94
MS
646 .suspend = tpm_inf_pnp_suspend,
647 .resume = tpm_inf_pnp_resume,
164dce82 648 .remove = tpm_inf_pnp_remove
ebb81fdb
MS
649};
650
651static int __init init_inf(void)
652{
e1d42c98 653 return pnp_register_driver(&tpm_inf_pnp_driver);
ebb81fdb
MS
654}
655
656static void __exit cleanup_inf(void)
657{
e1d42c98 658 pnp_unregister_driver(&tpm_inf_pnp_driver);
ebb81fdb
MS
659}
660
661module_init(init_inf);
662module_exit(cleanup_inf);
663
cbb2d5e4 664MODULE_AUTHOR("Marcel Selhorst <tpmdd@sirrix.com>");
f9abb020 665MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
93716b94 666MODULE_VERSION("1.9.2");
ebb81fdb 667MODULE_LICENSE("GPL");